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

import { ApiError } from "../api/http";
import { getTodayAttendance, syncRealtimeAttendance } from "../api/realtimeAttendance";
import type { RealtimeAttendanceResponse, TodayAttendanceItem } from "../api/types";
import DatePicker from "../components/DatePicker.vue";
import { useAuthStore } from "../stores/auth";

const auth = useAuthStore();
const selectedDate = ref(new Date().toISOString().slice(0, 10));
const response = ref<RealtimeAttendanceResponse | null>(null);
const loading = ref(false);
const syncing = ref(false);
const errorMessage = ref("");
const successMessage = ref("");
const employeeQuery = ref("");
const departmentFilter = ref("all");

const summary = computed(() => response.value?.summary);
const rows = computed(() => response.value?.items || []);
const canSync = computed(() => auth.hasPermission("attendance:realtime:sync"));
const departmentOptions = computed(() =>
  Array.from(new Set(rows.value.map((row) => row.department).filter(Boolean))).sort((a, b) => a.localeCompare(b, "zh-CN")),
);
const filteredRows = computed(() => {
  const query = employeeQuery.value.trim().toLowerCase();
  return rows.value.filter((row) => {
    const matchDepartment = departmentFilter.value === "all" || row.department === departmentFilter.value;
    const matchKeyword =
      !query ||
      [row.employee_name, row.employee_no, row.department, row.position]
        .filter(Boolean)
        .some((value) => value.toLowerCase().includes(query));
    return matchDepartment && matchKeyword;
  });
});
const hasRealtimeFilters = computed(() => departmentFilter.value !== "all" || employeeQuery.value.trim() !== "");
const syncStatusText = computed(() => {
  const syncedAt = response.value?.synced_at;
  if (syncedAt) {
    const time = formatSyncTime(syncedAt);
    return time ? `${time} 同步` : "已同步";
  }
  return response.value?.sync_job_id ? "已同步" : "未同步";
});
const syncStatusClass = computed(() => (response.value?.synced_at || response.value?.sync_job_id ? "green" : "neutral"));

onMounted(() => {
  void loadTodayAttendance();
});

async function loadTodayAttendance(): Promise<void> {
  loading.value = true;
  errorMessage.value = "";
  try {
    response.value = await getTodayAttendance(selectedDate.value);
  } catch (error) {
    errorMessage.value = error instanceof ApiError ? error.message : "实时考勤加载失败";
  } finally {
    loading.value = false;
  }
}

async function syncDingTalk(): Promise<void> {
  syncing.value = true;
  errorMessage.value = "";
  successMessage.value = "";
  try {
    response.value = await syncRealtimeAttendance(selectedDate.value);
    successMessage.value = "钉钉考勤已同步，薪资预估已刷新";
  } catch (error) {
    const message = error instanceof ApiError ? error.message : "钉钉同步失败";
    errorMessage.value = message.includes("dingtalk.app_key")
      ? "钉钉配置缺失，请先在 config/app_settings.json 中配置 app_key 和 app_secret"
      : message;
  } finally {
    syncing.value = false;
  }
}

function statusText(status: string): string {
  const map: Record<string, string> = {
    present: "已打卡",
    missing: "缺卡",
    leave: "请假",
    unchecked: "未打卡",
    absent: "未打卡",
  };
  return map[status] || status || "-";
}

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

function numberText(value: number, unit = ""): string {
  return `${Number(value || 0).toFixed(1)}${unit}`;
}

function formatSyncTime(value: string): string {
  const text = String(value || "").trim();
  const match = text.match(/(?:T|\s)(\d{2}):(\d{2})/);
  if (match) {
    return `${match[1]}:${match[2]}`;
  }

  const parsed = new Date(text.includes(" ") ? text.replace(" ", "T") : text);
  if (Number.isNaN(parsed.getTime())) {
    return "";
  }
  return new Intl.DateTimeFormat("zh-CN", {
    hour: "2-digit",
    minute: "2-digit",
    hour12: false,
  }).format(parsed);
}

function clearRealtimeFilters(): void {
  departmentFilter.value = "all";
  employeeQuery.value = "";
}

function rowKey(row: TodayAttendanceItem): string {
  return row.employee_id ? String(row.employee_id) : `${row.employee_no}-${row.employee_name}`;
}
</script>

<template>
  <div class="view-stack">
    <header class="page-header realtime-page-header">
      <div>
        <h1>实时考勤</h1>
        <p>查看今日打卡状态，并预估本月薪资进度。</p>
      </div>
      <div class="header-actions realtime-header-actions">
        <label class="field compact-field realtime-date-field">
          <span>考勤日期</span>
          <DatePicker v-model="selectedDate" mode="date" placeholder="请选择考勤日期" @change="loadTodayAttendance" />
        </label>
        <button class="primary-button" type="button" :disabled="!canSync || syncing" @click="syncDingTalk">
          <Loader2 v-if="syncing" class="spin" :size="18" aria-hidden="true" />
          <CloudCog v-else :size="18" aria-hidden="true" />
          <span>{{ syncing ? "同步中" : "同步钉钉" }}</span>
        </button>
      </div>
    </header>

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

    <section class="panel realtime-overview-panel">
      <div class="panel-header realtime-overview-header">
        <div class="realtime-overview-title">
          <h2>今日考勤与薪资预估</h2>
          <p>预估金额，最终以月度核算锁定结果为准。</p>
        </div>
        <span class="status-chip realtime-sync-chip" :class="syncStatusClass">
          {{ syncStatusText }}
        </span>
      </div>

      <div class="compact-stats-grid realtime-overview-stats">
        <div class="compact-stat">
          <span>在职员工</span>
          <strong>{{ summary?.employee_total || 0 }}</strong>
        </div>
        <div class="compact-stat">
          <span>已打卡</span>
          <strong>{{ summary?.checked_in_count || 0 }}</strong>
        </div>
        <div class="compact-stat">
          <span>未打卡</span>
          <strong>{{ summary?.unchecked_count || 0 }}</strong>
        </div>
        <div class="compact-stat">
          <span>迟到</span>
          <strong>{{ summary?.late_count || 0 }}</strong>
        </div>
        <div class="compact-stat">
          <span>缺卡</span>
          <strong>{{ summary?.missing_card_count || 0 }}</strong>
        </div>
        <div class="compact-stat">
          <span>预估实发</span>
          <strong>{{ money(summary?.estimated_net_total ?? 0) }}</strong>
        </div>
      </div>
    </section>

    <section class="panel">
      <div class="panel-header">
        <div>
          <h2>员工今日考勤</h2>
          <p>{{ response?.synced_at ? `最近同步：${response.synced_at}` : "可先查看已入库数据，也可同步钉钉刷新。" }}</p>
        </div>
      </div>

      <div v-if="rows.length" class="realtime-table-filter-bar">
        <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>
          <input v-model="employeeQuery" type="search" placeholder="姓名 / 编号 / 岗位" />
        </label>
        <button
          class="secondary-button realtime-clear-filter"
          type="button"
          :disabled="!hasRealtimeFilters"
          @click="clearRealtimeFilters"
        >
          清空
        </button>
        <span class="realtime-filter-result">显示 {{ filteredRows.length }} / {{ rows.length }} 人</span>
      </div>

      <div v-if="!rows.length && !loading" class="empty-state">
        <CalendarClock :size="38" aria-hidden="true" />
        <p>当前日期暂无考勤数据，可点击同步钉钉拉取在职员工打卡记录。</p>
      </div>

      <div v-else-if="!filteredRows.length" class="empty-state">
        <CalendarClock :size="38" aria-hidden="true" />
        <p>没有匹配当前部门或员工搜索条件的考勤记录。</p>
      </div>

      <div v-else class="table-wrap">
        <table class="data-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>
            </tr>
          </thead>
          <tbody>
            <tr v-for="row in filteredRows" :key="rowKey(row)">
              <td>
                <strong>{{ row.employee_name }}</strong>
                <span>{{ row.employee_no || "-" }}</span>
              </td>
              <td>
                <strong>{{ row.department || "-" }}</strong>
                <span>{{ row.position || "-" }}</span>
              </td>
              <td>{{ row.first_punch || "-" }}</td>
              <td>{{ row.last_punch || "-" }}</td>
              <td>{{ statusText(row.attendance_status) }}</td>
              <td>{{ row.late_minutes ? `${row.late_minutes} 分钟` : "-" }}</td>
              <td>{{ row.missing_card_count || "-" }}</td>
              <td>{{ numberText(row.leave_hours, "h") }}</td>
              <td>{{ numberText(row.today_overtime_hours, "h") }}</td>
              <td>{{ numberText(row.month_remaining_overtime_hours, "h") }}</td>
              <td>{{ money(row.estimated_net_salary) }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </section>
  </div>
</template>
