<template>
  <main class="config-root config-page">
    <div class="config-top-status row-between">
      <span class="socket-status" :class="socketRunning ? 'running' : 'stopped'">
        <i class="socket-dot" />
        Socket {{ socketRunning ? "运行中" : "未启动" }} (9501)
      </span>
      <div class="top-actions">
        <el-button type="primary" @click="saveConfig">保存配置</el-button>
        <el-button type="success" plain :disabled="socketRunning" @click="startSocketService">
          启动 Socket 服务
        </el-button>
        <el-button type="danger" plain :disabled="!socketRunning" @click="stopSocketService">
          停止 Socket 服务
        </el-button>
      </div>
    </div>

    <el-collapse v-model="activePanels" class="config-collapse">
      <el-collapse-item name="base">
        <template #title>
          <div class="card-header">基础配置</div>
        </template>
        <div class="panel-scroll">
          <el-form label-width="140px">
            <el-row :gutter="16">
              <el-col :span="8">
                <el-form-item label="主div总长度(px)">
                  <el-input-number v-model="draft.totalWidth" :min="1" :max="screenWidth" :step="1" />
                </el-form-item>
              </el-col>
              <el-col :span="8">
                <el-form-item label="主div高度(px)">
                  <el-input-number v-model="draft.segmentHeight" :min="1" :step="1" />
                </el-form-item>
              </el-col>
              <el-col :span="8">
                <el-form-item label="标尺显示">
                  <el-switch v-model="draft.showRuler" />
                </el-form-item>
              </el-col>
            </el-row>
          </el-form>
        </div>
      </el-collapse-item>

      <el-collapse-item name="segments">
        <template #title>
          <div class="card-header row-between">
            <span>分段列表（主屏宽度上限 {{ screenWidth }}px）</span>
            <el-button type="primary" plain size="small" @click.stop="addSegment">添加分段</el-button>
          </div>
        </template>
        <div class="panel-scroll">
          <el-table :data="draft.segments" border size="small">
            <el-table-column type="index" label="#" width="56" />
            <el-table-column label="段长度(px)" width="140">
              <template #default="{ row }">
                <el-input-number v-model="row.length" :min="1" :max="screenWidth" :step="1" />
              </template>
            </el-table-column>
            <el-table-column label="X" width="120">
              <template #default="{ row }">
                <el-input-number v-model="row.x" :min="0" :step="1" />
              </template>
            </el-table-column>
            <el-table-column label="Y" width="120">
              <template #default="{ row }">
                <el-input-number v-model="row.y" :min="0" :step="1" />
              </template>
            </el-table-column>
            <el-table-column label="操作" width="90">
              <template #default="{ $index }">
                <el-button type="danger" link @click="removeSegment($index)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>

          <el-divider content-position="left">应用后预览</el-divider>
          <el-table :data="appliedSegments" border size="small">
            <el-table-column type="index" label="#" width="56" />
            <el-table-column prop="sliceWidth" label="段长度(px)" width="140" />
            <el-table-column label="左顶点坐标">
              <template #default="{ row }">({{ row.left }}, {{ row.top }})</template>
            </el-table-column>
          </el-table>
        </div>
      </el-collapse-item>

      <el-collapse-item name="areas">
        <template #title>
          <div class="card-header row-between">
            <span>子div窗口区域</span>
            <el-button type="primary" plain size="small" @click.stop="addWindowArea">添加子div</el-button>
          </div>
        </template>
        <div class="panel-scroll panel-scroll--tall area-list">
        <el-card v-for="(area, index) in draft.windowAreas" :key="area.id" class="area-item" shadow="never">
          <template #header>
            <div class="row-between">
              <strong>子div {{ index + 1 }}</strong>
              <el-button type="danger" link @click="removeWindowArea(index)">删除</el-button>
            </div>
          </template>

          <el-form label-width="120px" size="small">
            <el-row :gutter="12">
              <el-col :span="6">
                <el-form-item label="窗口区域编号">
                  <el-input-number v-model="area.windowId" :min="1" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="时钟窗口">
                  <el-switch v-model="area.isClockWindow" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="宽度">
                  <el-input-number v-model="area.width" :min="1" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="高度">
                  <el-input-number v-model="area.height" :min="1" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="X">
                  <el-input-number v-model="area.x" :min="0" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="Y">
                  <el-input-number v-model="area.y" :min="0" />
                </el-form-item>
              </el-col>
            </el-row>

            <el-divider content-position="left">窗口号区域（占比 1）</el-divider>
            <el-row :gutter="12">
              <el-col :span="6">
                <el-form-item label="窗口编号">
                  <el-input v-model="area.windowNumber" />
                </el-form-item>
              </el-col>
              <el-col :span="4">
                <el-form-item label="圆圈边框">
                  <el-switch v-model="area.windowNumberCircle" />
                </el-form-item>
              </el-col>
              <el-col :span="4">
                <el-form-item label="字号">
                  <el-input-number v-model="area.windowNumberStyle.fontSize" :min="1" />
                </el-form-item>
              </el-col>
              <el-col :span="5">
                <el-form-item label="颜色">
                  <el-input v-model="area.windowNumberStyle.color" />
                </el-form-item>
              </el-col>
              <el-col :span="5">
                <el-form-item label="粗细">
                  <el-input-number v-model="area.windowNumberStyle.fontWeight" :min="100" :step="100" />
                </el-form-item>
              </el-col>
              <el-col :span="4">
                <el-form-item label="圆圈大小">
                  <el-input-number v-model="area.windowNumberCircleStyle.size" :min="1" />
                </el-form-item>
              </el-col>
              <el-col :span="4">
                <el-form-item label="边框粗细">
                  <el-input-number v-model="area.windowNumberCircleStyle.borderWidth" :min="1" />
                </el-form-item>
              </el-col>
              <el-col :span="4">
                <el-form-item label="圆角半径">
                  <el-input-number v-model="area.windowNumberCircleStyle.borderRadius" :min="0" />
                </el-form-item>
              </el-col>
            </el-row>

            <el-divider content-position="left">文本区域（占比 2.5，静态/动态=1:1）</el-divider>
            <el-row :gutter="12">
              <el-col :span="6">
                <el-form-item label="静态文本">
                  <el-input v-model="area.staticText" />
                </el-form-item>
              </el-col>
              <el-col :span="4">
                <el-form-item label="静态字号">
                  <el-input-number v-model="area.staticTextStyle.fontSize" :min="1" />
                </el-form-item>
              </el-col>
              <el-col :span="5">
                <el-form-item label="静态颜色">
                  <el-input v-model="area.staticTextStyle.color" />
                </el-form-item>
              </el-col>
              <el-col :span="5">
                <el-form-item label="静态粗细">
                  <el-input-number v-model="area.staticTextStyle.fontWeight" :min="100" :step="100" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="12">
              <el-col :span="6">
                <el-form-item label="动态文本">
                  <el-input v-model="area.dynamicText" />
                </el-form-item>
              </el-col>
              <el-col :span="4">
                <el-form-item label="动态字号">
                  <el-input-number v-model="area.dynamicTextStyle.fontSize" :min="1" />
                </el-form-item>
              </el-col>
              <el-col :span="5">
                <el-form-item label="动态颜色">
                  <el-input v-model="area.dynamicTextStyle.color" />
                </el-form-item>
              </el-col>
              <el-col :span="5">
                <el-form-item label="动态粗细">
                  <el-input-number v-model="area.dynamicTextStyle.fontWeight" :min="100" :step="100" />
                </el-form-item>
              </el-col>
            </el-row>
          </el-form>
        </el-card>
        </div>
      </el-collapse-item>

      <el-collapse-item name="subtitles">
        <template #title>
          <div class="card-header row-between">
            <span>滚动字幕区域</span>
            <el-button type="primary" plain size="small" @click.stop="addSubtitleArea">
              添加滚动字幕
            </el-button>
          </div>
        </template>
        <div class="panel-scroll area-list">
          <el-card
            v-for="(subtitle, index) in draft.subtitleAreas"
            :key="subtitle.id"
            class="area-item"
            shadow="never"
          >
            <template #header>
              <div class="row-between">
                <strong>字幕区域 {{ index + 1 }}</strong>
                <el-button type="danger" link @click="removeSubtitleArea(index)">删除</el-button>
              </div>
            </template>
            <el-form label-width="120px" size="small">
              <el-row :gutter="12">
                <el-col :span="6">
                  <el-form-item label="宽度">
                    <el-input-number v-model="subtitle.width" :min="1" />
                  </el-form-item>
                </el-col>
                <el-col :span="6">
                  <el-form-item label="高度">
                    <el-input-number v-model="subtitle.height" :min="1" />
                  </el-form-item>
                </el-col>
                <el-col :span="6">
                  <el-form-item label="X">
                    <el-input-number v-model="subtitle.x" :min="0" />
                  </el-form-item>
                </el-col>
                <el-col :span="6">
                  <el-form-item label="Y">
                    <el-input-number v-model="subtitle.y" :min="0" />
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="12">
                <el-col :span="8">
                  <el-form-item label="字幕文本">
                    <el-input v-model="subtitle.text" />
                  </el-form-item>
                </el-col>
                <el-col :span="4">
                  <el-form-item label="字号">
                    <el-input-number v-model="subtitle.textStyle.fontSize" :min="1" />
                  </el-form-item>
                </el-col>
                <el-col :span="4">
                  <el-form-item label="颜色">
                    <el-input v-model="subtitle.textStyle.color" />
                  </el-form-item>
                </el-col>
                <el-col :span="4">
                  <el-form-item label="粗细">
                    <el-input-number v-model="subtitle.textStyle.fontWeight" :min="100" :step="100" />
                  </el-form-item>
                </el-col>
                <el-col :span="4">
                  <el-form-item label="滚动速度">
                    <el-input-number v-model="subtitle.speed" :min="1" />
                  </el-form-item>
                </el-col>
              </el-row>
            </el-form>
          </el-card>
        </div>
      </el-collapse-item>
    </el-collapse>

    <div class="actions-row">
      <span class="version-text">版本号：V{{ appVersion }}</span>
      <el-button type="primary" plain :loading="checkingUpdate" @click="handleCheckUpdate">
        检查更新
      </el-button>
      <el-button @click="closeConfigWindow">关闭配置窗口</el-button>
      <el-button type="danger" @click="quitApplication">退出程序</el-button>
      <span class="save-hint">{{ saveMessage }}</span>
    </div>
  </main>
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, reactive, ref, watch } from "vue";
import { appWindow, currentMonitor } from "@tauri-apps/api/window";
import { invoke } from "@tauri-apps/api/tauri";
import { listen, type UnlistenFn } from "@tauri-apps/api/event";
import { ElMessage } from "element-plus";
import type {
  BroadcastConfig,
  ChildWindowAreaConfig,
  SegmentConfigItem,
  SubtitleAreaConfig,
} from "../models/config";
import { DEFAULT_BROADCAST_CONFIG } from "../models/config";
import { useBroadcastConfig } from "../composables/useBroadcastConfig";
import {
  buildSegmentsFromConfig,
  normalizeScreenWidth,
  normalizeSegmentConfigItem,
  normalizeSegmentHeight,
} from "../services/segmentService";

interface SocketStatusPayload {
  running: boolean;
  port: number;
}

interface AptUpdateCheckResult {
  packageName: string;
  currentVersion: string;
  installedVersion: string;
  candidateVersion: string;
  hasUpdate: boolean;
  sourceAvailable: boolean;
  updateCommand: string;
}

// 当前主屏宽度（用于限制总长度与分段长度）。
const screenWidth = ref(normalizeScreenWidth(window.screen.width || 1920));
const { config, patchConfig } = useBroadcastConfig();
const saveMessage = ref("修改后请点击“保存配置”。");
const activePanels = ref(["base", "segments", "areas", "subtitles"]);
const socketRunning = ref(false);
const checkingUpdate = ref(false);
const appVersion = ref("0.1.0");
const APT_SOURCE_ENTRY =
  "deb [arch=amd64 signed-by=/usr/share/keyrings/zyyun-archive-keyring.gpg] http://80.12.140.29:80/apt v10 main";
const APT_SOURCE_SETUP_COMMAND = `echo "${APT_SOURCE_ENTRY}" | sudo tee /etc/apt/sources.list.d/zyyun.list && sudo apt update`;
// 避免 store -> draft 回填触发“未保存”提示。
const syncingFromStore = ref(false);
let socketStatusUnlisten: UnlistenFn | null = null;

const draft = reactive<BroadcastConfig>({ ...DEFAULT_BROADCAST_CONFIG });

// 按当前草稿配置预演最终会应用到同步屏的分段数据。
const appliedSegments = computed(() =>
  buildSegmentsFromConfig(
    draft.segments,
    screenWidth.value,
    Math.min(draft.totalWidth, screenWidth.value),
    draft.segmentHeight,
  ),
);

/**
 * 深拷贝分段数组，避免引用同一对象导致联动副作用。
 */
function cloneSegments(segments: SegmentConfigItem[]) {
  return segments.map((item) => ({ ...item }));
}

function cloneWindowAreas(areas: ChildWindowAreaConfig[]) {
  return areas.map((item) => ({
    ...item,
    windowNumberCircleStyle: { ...item.windowNumberCircleStyle },
    windowNumberStyle: { ...item.windowNumberStyle },
    staticTextStyle: { ...item.staticTextStyle },
    dynamicTextStyle: { ...item.dynamicTextStyle },
  }));
}

function cloneSubtitleAreas(areas: SubtitleAreaConfig[]) {
  return areas.map((item) => ({
    ...item,
    textStyle: { ...item.textStyle },
  }));
}

function normalizeStyle(style: { fontSize: number; color: string; fontWeight: number }) {
  return {
    fontSize: Number.isFinite(style.fontSize) && style.fontSize > 0 ? Math.floor(style.fontSize) : 14,
    color: typeof style.color === "string" && style.color.trim() ? style.color.trim() : "#ffffff",
    fontWeight:
      Number.isFinite(style.fontWeight) && style.fontWeight >= 100 ? Math.floor(style.fontWeight) : 500,
  };
}

function createDefaultWindowArea(index: number): ChildWindowAreaConfig {
  return {
    id: `area-${Date.now()}-${index}`,
    windowId: index + 1,
    isClockWindow: false,
    width: 220,
    height: 48,
    x: 0,
    y: index * 50,
    windowNumber: String(index + 1),
    windowNumberCircle: false,
    windowNumberCircleStyle: {
      size: 36,
      borderWidth: 1,
      borderRadius: 18,
    },
    windowNumberStyle: {
      fontSize: 16,
      color: "#ffffff",
      fontWeight: 700,
    },
    staticText: "静态文本",
    staticTextStyle: {
      fontSize: 14,
      color: "#ffffff",
      fontWeight: 500,
    },
    dynamicText: "动态文本",
    dynamicTextStyle: {
      fontSize: 14,
      color: "#ffffff",
      fontWeight: 500,
    },
  };
}

function createDefaultSubtitleArea(index: number): SubtitleAreaConfig {
  return {
    id: `subtitle-${Date.now()}-${index}`,
    width: 420,
    height: 28,
    x: 0,
    y: 0,
    text: "欢迎使用同步屏系统",
    textStyle: {
      fontSize: 16,
      color: "#ffffff",
      fontWeight: 500,
    },
    speed: 80,
  };
}

/**
 * 添加一个新分段，默认放在当前末段之后。
 */
function addSegment() {
  const nextIndex = draft.segments.length;
  draft.segments.push(
    normalizeSegmentConfigItem(
      {
        length: Math.min(screenWidth.value, draft.totalWidth),
        x: 0,
        y: nextIndex * normalizeSegmentHeight(draft.segmentHeight),
      },
      nextIndex,
      screenWidth.value,
      draft.segmentHeight,
    ),
  );
  saveMessage.value = "已修改，点击“保存配置”后生效。";
}

/**
 * 删除指定下标的分段配置。
 */
function removeSegment(index: number) {
  draft.segments.splice(index, 1);
  saveMessage.value = "已修改，点击“保存配置”后生效。";
}

function addWindowArea() {
  draft.windowAreas.push(createDefaultWindowArea(draft.windowAreas.length));
  saveMessage.value = "已修改，点击“保存配置”后生效。";
}

function removeWindowArea(index: number) {
  draft.windowAreas.splice(index, 1);
  saveMessage.value = "已修改，点击“保存配置”后生效。";
}

function addSubtitleArea() {
  draft.subtitleAreas.push(createDefaultSubtitleArea(draft.subtitleAreas.length));
  saveMessage.value = "已修改，点击“保存配置”后生效。";
}

function removeSubtitleArea(index: number) {
  draft.subtitleAreas.splice(index, 1);
  saveMessage.value = "已修改，点击“保存配置”后生效。";
}

async function startSocketService() {
  try {
    const result = await invoke<SocketStatusPayload>("start_socket_service");
    socketRunning.value = result.running;
    saveMessage.value = "Socket 服务已启动，正在监听 9501 端口。";
  } catch (error) {
    saveMessage.value = `Socket 启动失败: ${String(error)}`;
  }
}

async function stopSocketService() {
  try {
    const result = await invoke<SocketStatusPayload>("stop_socket_service");
    socketRunning.value = result.running;
    saveMessage.value = "Socket 服务已停止。";
  } catch (error) {
    saveMessage.value = `Socket 停止失败: ${String(error)}`;
  }
}

async function quitApplication() {
  try {
    await invoke("quit_app");
  } catch (error) {
    saveMessage.value = `退出失败: ${String(error)}`;
  }
}

async function closeConfigWindow() {
  try {
    await appWindow.close();
  } catch (error) {
    saveMessage.value = `关闭配置窗口失败: ${String(error)}`;
  }
}

async function handleCheckUpdate() {
  if (checkingUpdate.value) {
    return;
  }

  checkingUpdate.value = true;
  try {
    const result = await invoke<AptUpdateCheckResult>("check_apt_update", {
      packageName: "broadcast-client",
      currentVersion: "0.1.0",
    });

    if (!result.sourceAvailable) {
      ElMessage.warning(
        `未检测到可用更新源，请先执行：${APT_SOURCE_SETUP_COMMAND}`,
      );
      return;
    }

    if (!result.hasUpdate) {
      ElMessage.success(`当前已是最新版本（${result.installedVersion}）`);
      return;
    }

    ElMessage.warning(
      `发现新版本 ${result.candidateVersion}，请在终端执行：${result.updateCommand}`,
    );
  } catch (error) {
    ElMessage.error(`检查更新失败：${String(error)}`);
  } finally {
    checkingUpdate.value = false;
  }
}

/**
 * 手动保存配置到持久化存储，并广播给同步屏窗口实时生效。
 */
async function saveConfig() {
  const totalWidth = Math.min(Math.max(1, Math.floor(draft.totalWidth)), screenWidth.value);
  const segmentHeight = normalizeSegmentHeight(draft.segmentHeight);
  const segments = draft.segments.map((item, index) =>
    normalizeSegmentConfigItem(item, index, screenWidth.value, segmentHeight),
  );
  const windowAreas = draft.windowAreas.map((area, index) => {
    const circleStyle = area.windowNumberCircleStyle ?? { size: 36, borderWidth: 1, borderRadius: 18 };
    return {
      id: area.id || `area-${index + 1}`,
    windowId:
      Number.isFinite(area.windowId) && area.windowId > 0 ? Math.floor(area.windowId) : index + 1,
    width: Number.isFinite(area.width) && area.width > 0 ? Math.floor(area.width) : 220,
    height: Number.isFinite(area.height) && area.height > 0 ? Math.floor(area.height) : 48,
    x: Number.isFinite(area.x) ? Math.max(0, Math.floor(area.x)) : 0,
    y: Number.isFinite(area.y) ? Math.max(0, Math.floor(area.y)) : 0,
    windowNumber: area.windowNumber || String(index + 1),
    isClockWindow: area.isClockWindow === true,
    windowNumberCircle: area.windowNumberCircle === true,
    windowNumberCircleStyle: {
      size: Number.isFinite(circleStyle.size) && circleStyle.size > 0 ? Math.floor(circleStyle.size) : 36,
      borderWidth:
        Number.isFinite(circleStyle.borderWidth) && circleStyle.borderWidth > 0
          ? Math.floor(circleStyle.borderWidth)
          : 1,
      borderRadius:
        Number.isFinite(circleStyle.borderRadius) && circleStyle.borderRadius >= 0
          ? Math.floor(circleStyle.borderRadius)
          : 18,
    },
    windowNumberStyle: normalizeStyle(area.windowNumberStyle),
    staticText: area.staticText || "静态文本",
    staticTextStyle: normalizeStyle(area.staticTextStyle),
    dynamicText: area.dynamicText || "动态文本",
      dynamicTextStyle: normalizeStyle(area.dynamicTextStyle),
    };
  });
  const subtitleAreas = draft.subtitleAreas.map((area, index) => ({
    id: area.id || `subtitle-${index + 1}`,
    width: Number.isFinite(area.width) && area.width > 0 ? Math.floor(area.width) : 420,
    height: Number.isFinite(area.height) && area.height > 0 ? Math.floor(area.height) : 28,
    x: Number.isFinite(area.x) ? Math.max(0, Math.floor(area.x)) : 0,
    y: Number.isFinite(area.y) ? Math.max(0, Math.floor(area.y)) : 0,
    text: area.text || "欢迎使用同步屏系统",
    textStyle: normalizeStyle(area.textStyle),
    speed: Number.isFinite(area.speed) && area.speed > 0 ? area.speed : 80,
  }));
  await patchConfig({
    totalWidth,
    segmentHeight,
    showRuler: draft.showRuler,
    segments,
    windowAreas,
    subtitleAreas,
  });
  saveMessage.value = "保存成功，已写入配置文件并实时应用。";
}

watch(
  config,
  (next) => {
    syncingFromStore.value = true;
    draft.totalWidth = Math.min(next.totalWidth, screenWidth.value);
    draft.segmentHeight = next.segmentHeight;
    draft.showRuler = next.showRuler;
    draft.segments = cloneSegments(next.segments);
    draft.windowAreas = cloneWindowAreas(next.windowAreas);
    draft.subtitleAreas = cloneSubtitleAreas(next.subtitleAreas);
    syncingFromStore.value = false;
  },
  { immediate: true, deep: true },
);

watch(
  () => ({
    totalWidth: draft.totalWidth,
    segmentHeight: draft.segmentHeight,
    showRuler: draft.showRuler,
    segments: draft.segments.map((item) => ({ ...item })),
    windowAreas: draft.windowAreas.map((item) => ({
      ...item,
      windowNumberCircleStyle: { ...item.windowNumberCircleStyle },
      windowNumberStyle: { ...item.windowNumberStyle },
      staticTextStyle: { ...item.staticTextStyle },
      dynamicTextStyle: { ...item.dynamicTextStyle },
    })),
    subtitleAreas: draft.subtitleAreas.map((item) => ({
      ...item,
      textStyle: { ...item.textStyle },
    })),
  }),
  () => {
    if (!syncingFromStore.value) {
      saveMessage.value = "已修改，点击“保存配置”后生效。";
    }
  },
  { deep: true },
);

onMounted(async () => {
  try {
    const monitor = await currentMonitor();
    const width = monitor?.size?.width;
    if (typeof width === "number" && Number.isFinite(width) && width > 0) {
      screenWidth.value = normalizeScreenWidth(width);
      if (draft.totalWidth > screenWidth.value) {
        draft.totalWidth = screenWidth.value;
      }
    }
  } catch {
    // 浏览器模式下忽略主屏信息读取失败。
  }

  try {
    const status = await invoke<SocketStatusPayload>("get_socket_service_status");
    socketRunning.value = status.running;
  } catch {
    socketRunning.value = false;
  }

  try {
    socketStatusUnlisten = await listen<SocketStatusPayload>("socket-status", (event) => {
      socketRunning.value = event.payload.running;
    });
  } catch {
    socketStatusUnlisten = null;
  }
});

onUnmounted(() => {
  socketStatusUnlisten?.();
  socketStatusUnlisten = null;
});
</script>
