<script setup lang="ts">
import { computed, ref, watch } from "vue";

import type { PayrollException, PayrollResult } from "../api/types";

const props = withDefaults(defineProps<{
  results: PayrollResult[];
  exceptions?: PayrollException[];
  embedded?: boolean;
}>(), {
  embedded: false,
  exceptions: () => [],
});

const keyword = ref("");
const departmentFilter = ref("all");
const statusFilter = ref("all");
const anomalyFilter = ref("all");
const selectedResult = ref<PayrollResult | null>(null);

const exceptionMap = computed(() => {
  const map = new Map<string, PayrollException[]>();
  for (const item of props.exceptions) {
    const keys = [item.employee_name, item.employee_no].filter(Boolean);
    for (const key of keys) {
      const list = map.get(key) || [];
      list.push(item);
      map.set(key, list);
    }
  }
  return map;
});

const departmentOptions = computed(() =>
  Array.from(new Set(props.results.map((item) => item.department).filter(Boolean))).sort((a, b) => a.localeCompare(b, "zh-CN")),
);

const filteredResults = computed(() => {
  const query = keyword.value.trim().toLowerCase();
  return props.results.filter((item) => {
    const matchKeyword =
      !query ||
      [item.name, item.department, item.position, item.attendance_group, item.note]
        .filter(Boolean)
        .some((value) => value.toLowerCase().includes(query));
    const matchDepartment = departmentFilter.value === "all" || item.department === departmentFilter.value;
    const hasWarning = hasAnomaly(item);
    const matchStatus =
      statusFilter.value === "all" ||
      (statusFilter.value === "normal" && !hasWarning) ||
      (statusFilter.value === "warning" && hasWarning);
    const matchAnomaly = anomalyFilter.value === "all" || anomalyTypes(item).includes(anomalyFilter.value);
    return matchKeyword && matchDepartment && matchStatus && matchAnomaly;
  });
});

watch(
  filteredResults,
  (items) => {
    if (!items.length) {
      selectedResult.value = null;
      return;
    }
    if (!selectedResult.value || !items.includes(selectedResult.value)) {
      selectedResult.value = items[0];
    }
  },
  { immediate: true },
);

function money(value: number | null): string {
  if (value === null || Number.isNaN(value)) {
    return "-";
  }
  return new Intl.NumberFormat("zh-CN", {
    style: "currency",
    currency: "CNY",
    maximumFractionDigits: 2,
  }).format(value);
}

function hours(value: number): string {
  return `${value.toFixed(1)}h`;
}

function modeLabel(value: string): string {
  const labels: Record<string, string> = {
    monthly: "包月",
    hourly: "计时",
    piecework: "计件",
    probation: "试用期",
  };
  return labels[value] || value;
}

function exceptionItems(item: PayrollResult): PayrollException[] {
  return [...(exceptionMap.value.get(item.name) || []), ...(exceptionMap.value.get(item.attendance_group) || [])];
}

function anomalyTypes(item: PayrollResult): string[] {
  const types = new Set<string>();
  for (const exception of exceptionItems(item)) {
    if (exception.exception_type) {
      types.add(exception.exception_type);
    }
  }
  if (item.note?.includes("未配置薪资档案")) {
    types.add("missing_salary_profile");
  }
  if (item.penalized_late_count > 0 || item.late_deduction > 0) {
    types.add("late_penalty");
  }
  if (item.missing_card_count > 0 || item.missing_card_deduction > 0) {
    types.add("missing_card");
  }
  if (item.remaining_overtime_hours < 0) {
    types.add("negative_remaining_overtime");
  }
  if ((item.net_salary || 0) <= 0) {
    types.add("salary_calculation_failed");
  }
  return Array.from(types);
}

function hasAnomaly(item: PayrollResult): boolean {
  return anomalyTypes(item).length > 0;
}

function anomalyLabel(item: PayrollResult): string {
  const types = anomalyTypes(item);
  if (!types.length) {
    return "正常";
  }
  const labels: Record<string, string> = {
    missing_employee: "未匹配员工",
    missing_salary_profile: "缺薪资档案",
    negative_remaining_overtime: "加班不足",
    late_penalty: "迟到扣款",
    missing_card: "缺卡",
    missing_attendance: "缺考勤",
    salary_calculation_failed: "工资异常",
  };
  return labels[types[0]] || "异常";
}

function anomalyClass(item: PayrollResult): string {
  return hasAnomaly(item) ? "warning" : "green";
}

function anomalySummary(item: PayrollResult): string {
  const parts = [
    item.penalized_late_count > 0 ? `迟到 ${item.penalized_late_count} 次` : "",
    item.missing_card_count > 0 ? `缺卡 ${item.missing_card_count} 次` : "",
    item.remaining_overtime_hours < 0 ? "剩余加班不足" : "",
    item.note?.includes("未配置薪资档案") ? "缺薪资档案" : "",
  ].filter(Boolean);
  return parts.join(" / ");
}

function selectResult(item: PayrollResult): void {
  selectedResult.value = item;
}

function closeDetail(): void {
  selectedResult.value = null;
}
</script>

<template>
  <section :class="embedded ? 'salary-detail-table-shell' : 'panel table-panel'">
    <div v-if="!embedded" class="panel-header">
      <div>
        <h2>员工工资结果</h2>
        <p>共 {{ results.length }} 条</p>
      </div>
    </div>

    <template v-if="embedded">
      <div class="salary-summary-toolbar">
        <label class="field salary-summary-search">
          <span>搜索</span>
          <input v-model="keyword" type="search" placeholder="员工、部门、岗位" />
        </label>
        <label class="field">
          <span>部门</span>
          <select v-model="departmentFilter">
            <option value="all">全部部门</option>
            <option v-for="department in departmentOptions" :key="department" :value="department">{{ department }}</option>
          </select>
        </label>
        <label class="field">
          <span>状态</span>
          <select v-model="statusFilter">
            <option value="all">全部状态</option>
            <option value="normal">正常</option>
            <option value="warning">有异常</option>
          </select>
        </label>
        <label class="field">
          <span>异常</span>
          <select v-model="anomalyFilter">
            <option value="all">全部异常</option>
            <option value="late_penalty">迟到扣款</option>
            <option value="missing_card">缺卡</option>
            <option value="negative_remaining_overtime">加班不足</option>
            <option value="missing_salary_profile">缺薪资档案</option>
            <option value="salary_calculation_failed">工资异常</option>
          </select>
        </label>
      </div>

      <div v-if="filteredResults.length" class="salary-summary-layout">
        <div class="table-wrap">
          <table class="data-table salary-summary-table">
            <thead>
              <tr>
                <th>姓名</th>
                <th>部门/岗位</th>
                <th>应发工资</th>
                <th>实发工资</th>
                <th>异常标记</th>
                <th>操作</th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="item in filteredResults"
                :key="`${item.name}-${item.department}-${item.position}`"
                :class="{ 'is-selected': selectedResult === item, 'has-warning': hasAnomaly(item) }"
                @click="selectResult(item)"
              >
                <td>
                  <button class="link-button salary-name-button" type="button" @click.stop="selectResult(item)">
                    <strong>{{ item.name }}</strong>
                  </button>
                  <span>{{ item.attendance_group || "默认考勤组" }}</span>
                </td>
                <td>
                  <strong>{{ item.department || "-" }}</strong>
                  <span>{{ item.position || "-" }}</span>
                </td>
                <td class="mono">{{ money(item.gross_salary) }}</td>
                <td class="mono strong">{{ money(item.net_salary) }}</td>
                <td>
                  <span class="status-chip" :class="anomalyClass(item)">{{ anomalyLabel(item) }}</span>
                  <small v-if="anomalySummary(item)" class="salary-anomaly-note">{{ anomalySummary(item) }}</small>
                </td>
                <td>
                  <button class="link-button" type="button" @click.stop="selectResult(item)">查看构成</button>
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <aside v-if="selectedResult" class="salary-detail-drawer" aria-label="员工薪资构成">
          <div class="salary-detail-drawer-header">
            <div>
              <span>薪资构成</span>
              <h3>{{ selectedResult.name }}</h3>
              <p>{{ selectedResult.department || "-" }} · {{ selectedResult.position || "-" }}</p>
            </div>
            <button class="link-button" type="button" @click="closeDetail">关闭</button>
          </div>
          <div>
            <span>薪资模式</span>
            <strong>{{ modeLabel(selectedResult.salary_mode) }}</strong>
          </div>
          <div>
            <span>出勤/缺勤</span>
            <strong>{{ selectedResult.attendance_days }} / {{ selectedResult.absence_days }}</strong>
          </div>
          <div>
            <span>实际工时</span>
            <strong>{{ hours(selectedResult.actual_work_hours) }}</strong>
          </div>
          <div>
            <span>剩余加班</span>
            <strong>{{ hours(selectedResult.remaining_overtime_hours) }}</strong>
          </div>
          <div>
            <span>请假工时</span>
            <strong>{{ hours(selectedResult.leave_hours) }}</strong>
          </div>
          <div>
            <span>迟到扣款</span>
            <strong>{{ money(selectedResult.late_deduction) }}</strong>
          </div>
          <div>
            <span>缺卡扣款</span>
            <strong>{{ money(selectedResult.missing_card_deduction) }}</strong>
          </div>
          <div>
            <span>提成</span>
            <strong>{{ money(selectedResult.commission_amount) }}</strong>
          </div>
          <div>
            <span>基础工资</span>
            <strong>{{ money(selectedResult.base_pay) }}</strong>
          </div>
          <div>
            <span>加班费</span>
            <strong>{{ money(selectedResult.overtime_pay) }}</strong>
          </div>
          <div>
            <span>应发工资</span>
            <strong>{{ money(selectedResult.gross_salary) }}</strong>
          </div>
          <div>
            <span>实发工资</span>
            <strong>{{ money(selectedResult.net_salary) }}</strong>
          </div>
          <p class="salary-detail-note">{{ selectedResult.note || anomalySummary(selectedResult) || "无备注" }}</p>
        </aside>
      </div>

      <div v-else class="empty-state">
        <p>没有匹配当前筛选条件的工资结果</p>
      </div>
    </template>

    <div v-else-if="results.length" class="table-wrap">
      <table class="data-table salary-detail-table">
        <thead>
          <tr>
            <th>姓名</th>
            <th>月份/模式</th>
            <th>部门</th>
            <th>岗位</th>
            <th>出勤/缺勤</th>
            <th>推算加班</th>
            <th>请假工时</th>
            <th>剩余加班</th>
            <th>加班拆分</th>
            <th>迟到扣款</th>
            <th>缺卡扣款</th>
            <th>底薪</th>
            <th>基础工资</th>
            <th>提成</th>
            <th>加班单价</th>
            <th>加班费</th>
            <th>实发工资</th>
            <th>备注</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="item in results" :key="`${item.name}-${item.department}-${item.position}`">
            <td>
              <strong>{{ item.name }}</strong>
              <span>{{ item.attendance_group || "默认考勤组" }}</span>
            </td>
            <td>
              <strong>{{ item.salary_month || "-" }}</strong>
              <span>{{ modeLabel(item.salary_mode) }}</span>
            </td>
            <td>{{ item.department || "-" }}</td>
            <td>{{ item.position || "-" }}</td>
            <td class="mono">
              {{ item.attendance_days }} / {{ item.absence_days }}
              <span>{{ hours(item.actual_work_hours) }}</span>
            </td>
            <td class="mono">{{ hours(item.punch_overtime_hours) }}</td>
            <td class="mono">{{ hours(item.leave_hours) }}</td>
            <td class="mono strong">{{ hours(item.remaining_overtime_hours) }}</td>
            <td class="mono">
              工作日 {{ hours(item.workday_overtime_hours) }}
              <span>周末 {{ hours(item.weekend_overtime_hours) }}</span>
              <span>节假日 {{ hours(item.holiday_overtime_hours) }}</span>
            </td>
            <td class="mono">{{ money(item.late_deduction) }}</td>
            <td class="mono">{{ money(item.missing_card_deduction) }}</td>
            <td class="mono">{{ money(item.base_salary) }}</td>
            <td class="mono">{{ money(item.base_pay) }}</td>
            <td class="mono">{{ money(item.commission_amount) }}</td>
            <td class="mono">
              {{ money(item.overtime_rate) }}
              <span>{{ money(item.weekend_overtime_rate) }}</span>
              <span>{{ money(item.holiday_overtime_rate) }}</span>
            </td>
            <td class="mono">{{ money(item.overtime_pay) }}</td>
            <td class="mono strong">{{ money(item.net_salary) }}</td>
            <td class="note-cell">{{ item.note || "-" }}</td>
          </tr>
        </tbody>
      </table>
    </div>

    <div v-else class="empty-state">
      <p>暂无工资结果</p>
    </div>
  </section>
</template>
