<script setup lang="ts">
import { Loader2, Save, Settings2, SlidersHorizontal } from "@lucide/vue";
import { computed, onMounted, ref } from "vue";

import { ensureDefaultConfigs, listSalaryConfigs, updateSalaryConfig } from "../api/configs";
import { ApiError } from "../api/http";
import type { SalaryConfigRecord } from "../api/types";
import StatCard from "../components/StatCard.vue";

const configs = ref<SalaryConfigRecord[]>([]);
const activeGroup = ref("");
const loading = ref(false);
const savingKey = ref("");
const errorMessage = ref("");
const successMessage = ref("");

type RulePresentation = {
  name: string;
  purpose: string;
};

const groupLabels: Record<string, string> = {
  attendance: "考勤规则",
  payroll: "薪资规则",
  overtime: "加班规则",
  leave: "请假规则",
  penalty: "扣款规则",
};

const groupOrder = ["attendance", "payroll", "overtime", "leave", "penalty"];
const weekdayOptions = [
  { value: 0, label: "周一" },
  { value: 1, label: "周二" },
  { value: 2, label: "周三" },
  { value: 3, label: "周四" },
  { value: 4, label: "周五" },
  { value: 5, label: "周六" },
  { value: 6, label: "周日" },
];

const rulePresentation: Record<string, RulePresentation> = {
  "attendance.on_work_time": {
    name: "上班时间",
    purpose: "员工晚于这个时间打卡，系统会开始判断迟到。",
  },
  "attendance.off_work_time": {
    name: "下班时间",
    purpose: "用于判断下班后是否产生加班工时。",
  },
  "attendance.overtime_round_minutes": {
    name: "加班取整方式",
    purpose: "下班打卡超过下班时间后，加班时长按这个分钟数向下取整。",
  },
  "attendance.standard_daily_hours": {
    name: "每天标准工时",
    purpose: "计时工资和请假折算会按这个工时作为一天。",
  },
  "attendance.minor_late_minutes": {
    name: "轻微迟到范围",
    purpose: "迟到不超过这个分钟数，先按轻微迟到统计。",
  },
  "attendance.minor_late_free_times": {
    name: "轻微迟到免扣次数",
    purpose: "轻微迟到在这个次数以内不扣款，超过后按次扣款。",
  },
  "attendance.late_penalty": {
    name: "迟到扣款金额",
    purpose: "超过轻微迟到免扣次数，或迟到超过轻微范围时，每次扣这个金额。",
  },
  "attendance.missing_card_penalty": {
    name: "缺卡扣款金额",
    purpose: "员工上班或下班缺少打卡记录时，每次扣这个金额。",
  },
  "attendance.weekend_days": {
    name: "周末加班日",
    purpose: "用于识别哪些日期按周末加班规则计算。",
  },
  "attendance.legal_holidays": {
    name: "法定节假日",
    purpose: "用于识别哪些日期按节假日加班规则计算。",
  },
  "attendance.leave_keywords": {
    name: "请假识别词",
    purpose: "钉钉或 Excel 中出现这些文字时，系统会按请假或调休处理。",
  },
  "payroll.default_overtime_rate": {
    name: "工作日加班单价",
    purpose: "员工薪资档案没有维护加班单价时，默认按这个单价计算。",
  },
  "payroll.default_weekend_overtime_rate": {
    name: "周末加班单价",
    purpose: "员工薪资档案没有维护周末加班单价时，默认按这个单价计算。",
  },
  "payroll.default_holiday_overtime_rate": {
    name: "节假日加班单价",
    purpose: "员工薪资档案没有维护节假日加班单价时，默认按这个单价计算。",
  },
};

const groupOptions = computed(() => {
  const values = Array.from(new Set(configs.value.map((item) => item.config_group))).filter(Boolean);
  return values
    .sort((left, right) => {
      const leftIndex = groupOrder.indexOf(left);
      const rightIndex = groupOrder.indexOf(right);
      if (leftIndex !== -1 || rightIndex !== -1) {
        return (leftIndex === -1 ? 99 : leftIndex) - (rightIndex === -1 ? 99 : rightIndex);
      }
      return groupLabel(left).localeCompare(groupLabel(right), "zh-Hans-CN");
    })
    .map((value) => ({ value, label: groupLabel(value) }));
});
const visibleConfigs = computed(() => {
  if (!activeGroup.value) {
    return configs.value;
  }
  return configs.value.filter((item) => item.config_group === activeGroup.value);
});
const enabledCount = computed(() => configs.value.filter((item) => item.is_enabled).length);
const activeGroupLabel = computed(() => (activeGroup.value ? groupLabel(activeGroup.value) : "全部规则"));

onMounted(loadData);

async function loadData(): Promise<void> {
  loading.value = true;
  errorMessage.value = "";
  try {
    configs.value = await listSalaryConfigs();
  } catch (error) {
    errorMessage.value = error instanceof ApiError ? error.message : "配置加载失败";
  } finally {
    loading.value = false;
  }
}

async function seedDefaults(): Promise<void> {
  loading.value = true;
  errorMessage.value = "";
  successMessage.value = "";
  try {
    const response = await ensureDefaultConfigs();
    successMessage.value = `${response.message}，新增 ${response.created_count} 项`;
    await loadData();
  } catch (error) {
    errorMessage.value = error instanceof ApiError ? error.message : "默认配置初始化失败";
  } finally {
    loading.value = false;
  }
}

async function saveConfig(config: SalaryConfigRecord): Promise<void> {
  savingKey.value = config.config_key;
  errorMessage.value = "";
  successMessage.value = "";
  try {
    const updated = await updateSalaryConfig(config.config_key, {
      config_name: config.config_name,
      config_group: config.config_group,
      config_value: config.config_value,
      value_type: config.value_type,
      is_enabled: config.is_enabled,
      remark: config.remark,
    });
    configs.value = configs.value.map((item) => (item.id === updated.id ? updated : item));
    successMessage.value = "配置已保存";
  } catch (error) {
    errorMessage.value = error instanceof ApiError ? error.message : "配置保存失败";
  } finally {
    savingKey.value = "";
  }
}

function groupLabel(group: string): string {
  return groupLabels[group] || "其他规则";
}

function configTitle(config: SalaryConfigRecord): string {
  return rulePresentation[config.config_key]?.name || config.config_name || "未命名规则";
}

function configPurpose(config: SalaryConfigRecord): string {
  return rulePresentation[config.config_key]?.purpose || config.remark || "影响工资核算时的自动判断规则。";
}

function isLongValue(config: SalaryConfigRecord): boolean {
  return isTextListRule(config) || config.config_value.length > 18;
}

function formatConfigValue(config: SalaryConfigRecord): string {
  const value = config.config_value.trim();
  switch (config.config_key) {
    case "attendance.on_work_time":
      return value ? `${value} 后开始判断迟到` : "未设置上班时间";
    case "attendance.off_work_time":
      return value ? `${value} 后判断加班` : "未设置下班时间";
    case "attendance.overtime_round_minutes":
      return value ? `按 ${value} 分钟向下取整` : "未设置取整方式";
    case "attendance.standard_daily_hours":
      return value ? `每天 ${value} 小时` : "未设置标准工时";
    case "attendance.minor_late_minutes":
      return value ? `${value} 分钟内算轻微迟到` : "未设置轻微迟到范围";
    case "attendance.minor_late_free_times":
      return value ? `每月前 ${value} 次不扣款` : "未设置免扣次数";
    case "attendance.late_penalty":
      return value ? `每次扣 ${formatMoney(value)}` : "未设置迟到扣款";
    case "attendance.missing_card_penalty":
      return value ? `每次扣 ${formatMoney(value)}` : "未设置缺卡扣款";
    case "attendance.weekend_days":
      return `按 ${formatWeekdays(value)} 识别周末`;
    case "attendance.legal_holidays":
      return formatHolidaySummary(value);
    case "attendance.leave_keywords":
      return formatKeywordSummary(value);
    case "payroll.default_overtime_rate":
    case "payroll.default_weekend_overtime_rate":
    case "payroll.default_holiday_overtime_rate":
      return value ? `${formatMoney(value)} / 小时` : "未设置默认单价";
    default:
      return value || "未设置";
  }
}

function formatMoney(value: string): string {
  const amount = Number(value);
  if (!Number.isFinite(amount)) {
    return value;
  }
  return `¥${amount.toFixed(2).replace(/\.00$/, "")}`;
}

function formatWeekdays(value: string): string {
  const weekdayNames = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
  const items = parseArray(value);
  const labels = items
    .map((item) => Number(item))
    .filter((item) => Number.isInteger(item) && item >= 0 && item <= 6)
    .map((item) => weekdayNames[item]);
  return labels.length ? labels.join("、") : "未设置";
}

function formatHolidaySummary(value: string): string {
  const items = parseArray(value);
  if (!items.length) {
    return "暂未设置节假日";
  }
  return `已设置 ${items.length} 天节假日`;
}

function formatKeywordSummary(value: string): string {
  const items = parseArray(value).map((item) => String(item)).filter(Boolean);
  if (!items.length) {
    return "暂未设置请假识别词";
  }
  const visibleItems = items.slice(0, 5).join("、");
  return items.length > 5 ? `${visibleItems} 等 ${items.length} 个词` : visibleItems;
}

function parseArray(value: string): unknown[] {
  try {
    const parsed = JSON.parse(value || "[]");
    return Array.isArray(parsed) ? parsed : [];
  } catch {
    return [];
  }
}

function isWeekdayRule(config: SalaryConfigRecord): boolean {
  return config.config_key === "attendance.weekend_days";
}

function isTextListRule(config: SalaryConfigRecord): boolean {
  return ["attendance.legal_holidays", "attendance.leave_keywords"].includes(config.config_key);
}

function displayEditValue(config: SalaryConfigRecord): string {
  if (config.config_key === "attendance.legal_holidays") {
    return parseArray(config.config_value).map((item) => String(item)).filter(Boolean).join("\n");
  }
  if (config.config_key === "attendance.leave_keywords") {
    return parseArray(config.config_value).map((item) => String(item)).filter(Boolean).join("、");
  }
  return config.config_value;
}

function updateDisplayValue(config: SalaryConfigRecord, event: Event): void {
  const target = event.target as HTMLInputElement | HTMLTextAreaElement;
  const value = target.value;
  if (config.config_key === "attendance.legal_holidays" || config.config_key === "attendance.leave_keywords") {
    config.config_value = JSON.stringify(splitListValue(value), null, 0);
    return;
  }
  config.config_value = value;
}

function splitListValue(value: string): string[] {
  return value
    .split(/[\n,，、;；\s]+/)
    .map((item) => item.trim())
    .filter(Boolean);
}

function textListPlaceholder(config: SalaryConfigRecord): string {
  if (config.config_key === "attendance.legal_holidays") {
    return "一行一个日期，例如 2026-10-01";
  }
  if (config.config_key === "attendance.leave_keywords") {
    return "例如：调休、请假、事假、病假";
  }
  return "请输入当前设置";
}

function isWeekdaySelected(config: SalaryConfigRecord, weekday: number): boolean {
  return parseArray(config.config_value).map((item) => Number(item)).includes(weekday);
}

function toggleWeekday(config: SalaryConfigRecord, weekday: number, event: Event): void {
  const target = event.target as HTMLInputElement;
  const selected = new Set(parseArray(config.config_value).map((item) => Number(item)).filter((item) => Number.isInteger(item)));
  if (target.checked) {
    selected.add(weekday);
  } else {
    selected.delete(weekday);
  }
  config.config_value = JSON.stringify(Array.from(selected).sort((left, right) => left - right));
}
</script>

<template>
  <div class="view-stack">
    <header class="page-header">
      <div>
        <h1>薪资规则设置</h1>
        <p>设置考勤、加班、迟到、缺卡和请假等工资核算规则。</p>
      </div>
      <div class="header-actions">
        <button class="secondary-button" type="button" :disabled="loading" @click="seedDefaults">
          <Settings2 :size="18" aria-hidden="true" />
          <span>恢复默认规则</span>
        </button>
      </div>
    </header>

    <section class="summary-strip">
      <StatCard title="规则总数" :value="String(configs.length)" :icon="SlidersHorizontal" tone="blue" meta="可维护规则" />
      <StatCard title="使用中" :value="String(enabledCount)" :icon="Settings2" tone="green" meta="会参与核算" />
      <StatCard title="当前查看" :value="activeGroupLabel" :icon="Settings2" tone="neutral" meta="规则范围" />
    </section>

    <section class="panel table-panel rules-panel">
      <div class="panel-header">
        <div>
          <h2>规则清单</h2>
          <p>共 {{ visibleConfigs.length }} 项，修改后点击保存生效</p>
        </div>
        <select v-model="activeGroup" class="compact-select">
          <option value="">全部规则</option>
          <option v-for="group in groupOptions" :key="group.value" :value="group.value">{{ group.label }}</option>
        </select>
      </div>
      <div class="table-wrap">
        <table class="data-table rules-table">
          <thead>
            <tr>
              <th>规则</th>
              <th>当前设置</th>
              <th>是否使用</th>
              <th>用途说明</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="config in visibleConfigs" :key="config.config_key">
              <td class="rule-name-cell">
                <strong>{{ configTitle(config) }}</strong>
                <span class="rule-group-chip">{{ groupLabel(config.config_group) }}</span>
              </td>
              <td class="rule-value-cell">
                <span class="rule-value-preview">{{ formatConfigValue(config) }}</span>
                <div v-if="isWeekdayRule(config)" class="weekday-toggle-group" :aria-label="`${configTitle(config)}当前设置`">
                  <label
                    v-for="weekday in weekdayOptions"
                    :key="weekday.value"
                    class="weekday-toggle"
                    :class="{ 'is-selected': isWeekdaySelected(config, weekday.value) }"
                  >
                    <input
                      type="checkbox"
                      :checked="isWeekdaySelected(config, weekday.value)"
                      @change="toggleWeekday(config, weekday.value, $event)"
                    />
                    <span>{{ weekday.label }}</span>
                  </label>
                </div>
                <textarea
                  v-else-if="isLongValue(config)"
                  :value="displayEditValue(config)"
                  class="table-textarea rule-value-input"
                  :placeholder="textListPlaceholder(config)"
                  :aria-label="`${configTitle(config)}当前设置`"
                  @input="updateDisplayValue(config, $event)"
                />
                <input
                  v-else
                  :value="displayEditValue(config)"
                  class="table-input rule-value-input"
                  type="text"
                  :aria-label="`${configTitle(config)}当前设置`"
                  @input="updateDisplayValue(config, $event)"
                />
              </td>
              <td>
                <label class="checkbox-line">
                  <input v-model="config.is_enabled" type="checkbox" />
                  <span>{{ config.is_enabled ? "使用" : "不用" }}</span>
                </label>
              </td>
              <td class="rule-purpose">
                <p>{{ configPurpose(config) }}</p>
              </td>
              <td>
                <button class="link-button" type="button" :disabled="savingKey === config.config_key" @click="saveConfig(config)">
                  <Loader2 v-if="savingKey === config.config_key" class="spin" :size="15" aria-hidden="true" />
                  <Save v-else :size="15" aria-hidden="true" />
                  <span>保存</span>
                </button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <div v-if="!visibleConfigs.length && !loading" class="empty-state">
        <p>暂无配置项</p>
      </div>
    </section>

    <p v-if="errorMessage" class="form-error">{{ errorMessage }}</p>
    <p v-if="successMessage" class="form-success">{{ successMessage }}</p>
  </div>
</template>
