"use client";

/**
 * 请假审批页 - 教师请假申请管理
 *
 * 数据来源（P7 扩展，MSW mock）：
 * - GraphQL LeaveRequestsQuery：按 dataScope/status 筛选 + 分页
 * - GraphQL ApproveLeaveRequestMutation：批准/拒绝请假
 * - GraphQL SubmitLeaveRequestMutation：教师提交请假申请
 *
 * 功能：
 * - dataScope 筛选（我的/本班/本年级/全校）
 * - 状态筛选（全部/待审批/已批准/已拒绝）
 * - 审批对话框（批准/拒绝 + 评论）
 * - 提交请假申请模态框（类型/起止日期/原因）
 *
 * 维护者：ai13（teacher-portal）
 */

import { useState, useMemo } from "react";
import { useQuery, useMutation } from "urql";
import { Loading, Empty } from "@edu/ui-components";
import {
  LeaveRequestsQuery,
  ApproveLeaveRequestMutation,
  SubmitLeaveRequestMutation,
} from "@/lib/graphql-p7-admin";
import type {
  LeaveRequest,
  LeaveRequestsFilter,
  LeaveType,
  LeaveStatus,
  ApproveLeaveRequestInput,
  SubmitLeaveRequestInput,
} from "@/lib/graphql-p7-admin";
import type { DataScope } from "@/lib/graphql";
import {
  DATA_SCOPES,
  LEAVE_TYPE_LABEL,
  LEAVE_STATUS_LABEL,
} from "@/mocks/fixtures/leave-requests";

const LEAVE_TYPES: { value: LeaveType; label: string }[] = [
  { value: "SICK", label: "病假" },
  { value: "PERSONAL", label: "事假" },
  { value: "ANNUAL", label: "年假" },
  { value: "OTHER", label: "其他" },
];

const STATUS_FILTERS: { value: LeaveStatus | "ALL"; label: string }[] = [
  { value: "ALL", label: "全部" },
  { value: "PENDING", label: "待审批" },
  { value: "APPROVED", label: "已批准" },
  { value: "REJECTED", label: "已拒绝" },
];

function statusBadgeClass(status: LeaveStatus): string {
  switch (status) {
    case "PENDING":
      return "text-warning border-warning";
    case "APPROVED":
      return "text-success border-success";
    case "REJECTED":
      return "text-danger border-danger";
    default:
      return "text-ink-muted border-rule";
  }
}

function todayStr(): string {
  const d = new Date();
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
}

export default function LeavePage(): React.ReactNode {
  const [dataScope, setDataScope] = useState<DataScope>("SELF");
  const [statusFilter, setStatusFilter] = useState<LeaveStatus | "ALL">("ALL");
  const [page, setPage] = useState(1);
  const pageSize = 20;

  // 审批对话框状态
  const [reviewTarget, setReviewTarget] = useState<LeaveRequest | null>(null);
  const [reviewAction, setReviewAction] = useState<"APPROVE" | "REJECT">(
    "APPROVE",
  );
  const [reviewComment, setReviewComment] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [reviewError, setReviewError] = useState<string | null>(null);

  // 提交请假对话框状态
  const [showSubmit, setShowSubmit] = useState(false);
  const [formType, setFormType] = useState<LeaveType>("SICK");
  const [formStart, setFormStart] = useState(todayStr());
  const [formEnd, setFormEnd] = useState(todayStr());
  const [formReason, setFormReason] = useState("");
  const [formSubmitting, setFormSubmitting] = useState(false);
  const [formError, setFormError] = useState<string | null>(null);
  const [formSuccess, setFormSuccess] = useState<string | null>(null);

  const filter: LeaveRequestsFilter = useMemo(
    () => ({
      dataScope,
      status: statusFilter === "ALL" ? null : statusFilter,
      page,
      pageSize,
    }),
    [dataScope, statusFilter, page],
  );

  const [result, reexecute] = useQuery({
    query: LeaveRequestsQuery,
    variables: { filter },
  });

  const [, approveLeave] = useMutation(ApproveLeaveRequestMutation);
  const [, submitLeave] = useMutation(SubmitLeaveRequestMutation);

  const data = result.data?.leaveRequests;
  const items: LeaveRequest[] = data?.items ?? [];
  const total = data?.total ?? 0;

  const openReview = (
    request: LeaveRequest,
    action: "APPROVE" | "REJECT",
  ): void => {
    setReviewTarget(request);
    setReviewAction(action);
    setReviewComment("");
    setReviewError(null);
  };

  const closeReview = (): void => {
    setReviewTarget(null);
    setReviewComment("");
    setReviewError(null);
  };

  const handleApprove = async (): Promise<void> => {
    if (!reviewTarget) return;
    setSubmitting(true);
    setReviewError(null);
    const input: ApproveLeaveRequestInput = {
      requestId: reviewTarget.id,
      action: reviewAction,
      comment: reviewComment.trim() || null,
    };
    const res = await approveLeave({ input });
    setSubmitting(false);
    if (res.error) {
      setReviewError(res.error.message);
      return;
    }
    closeReview();
    reexecute({ requestPolicy: "network-only" });
  };

  const handleSubmitLeave = async (): Promise<void> => {
    if (!formStart || !formEnd || !formReason.trim()) {
      setFormError("请填写起止日期和原因");
      return;
    }
    if (formEnd < formStart) {
      setFormError("结束日期不能早于开始日期");
      return;
    }
    setFormSubmitting(true);
    setFormError(null);
    setFormSuccess(null);
    const input: SubmitLeaveRequestInput = {
      type: formType,
      startDate: formStart,
      endDate: formEnd,
      reason: formReason.trim(),
    };
    const res = await submitLeave({ input });
    setFormSubmitting(false);
    if (res.error) {
      setFormError(res.error.message);
      return;
    }
    setFormSuccess(
      `已提交：${res.data?.submitLeaveRequest?.requestId ?? "—"}，等待审批`,
    );
    // 重置表单
    setFormType("SICK");
    setFormStart(todayStr());
    setFormEnd(todayStr());
    setFormReason("");
    reexecute({ requestPolicy: "network-only" });
  };

  const closeSubmit = (): void => {
    setShowSubmit(false);
    setFormError(null);
    setFormSuccess(null);
    setFormReason("");
  };

  return (
    <div className="px-10 py-10">
      <header className="mb-8 flex items-baseline justify-between">
        <div>
          <h1 className="text-3xl font-serif text-ink">请假管理</h1>
          <p className="mt-1 text-sm text-ink-muted">
            GraphQL LeaveRequestsQuery + ApproveLeaveRequestMutation +
            SubmitLeaveRequestMutation（P7 扩展，MSW mock）
          </p>
        </div>
        <button
          type="button"
          onClick={() => {
            setShowSubmit(true);
            setFormSuccess(null);
          }}
          className="px-4 py-2 text-sm text-ink-on-accent bg-accent rounded-button hover:bg-accent-hover"
        >
          提交请假申请
        </button>
      </header>

      <div className="rule-thin mb-8" />

      {/* 筛选栏 */}
      <section className="mb-8">
        <div className="flex items-center justify-between flex-wrap gap-4">
          <div className="flex items-center gap-2 flex-wrap">
            <label className="text-tiny uppercase tracking-wide text-ink-muted">
              范围：
            </label>
            {DATA_SCOPES.map((s) => {
              const active = dataScope === s.value;
              return (
                <button
                  key={s.value}
                  type="button"
                  onClick={() => {
                    setDataScope(s.value);
                    setPage(1);
                  }}
                  className={`px-3 py-1 text-tiny uppercase tracking-wide rounded-button border transition-colors ${
                    active
                      ? "bg-accent text-ink-on-accent border-accent"
                      : "bg-transparent text-ink-muted border-rule hover:text-ink"
                  }`}
                >
                  {s.label}
                </button>
              );
            })}
          </div>
          <div className="flex items-center gap-2 flex-wrap">
            <label className="text-tiny uppercase tracking-wide text-ink-muted">
              状态：
            </label>
            {STATUS_FILTERS.map((s) => {
              const active = statusFilter === s.value;
              return (
                <button
                  key={s.value}
                  type="button"
                  onClick={() => {
                    setStatusFilter(s.value);
                    setPage(1);
                  }}
                  className={`px-3 py-1 text-tiny uppercase tracking-wide rounded-button border transition-colors ${
                    active
                      ? "bg-accent text-ink-on-accent border-accent"
                      : "bg-transparent text-ink-muted border-rule hover:text-ink"
                  }`}
                >
                  {s.label}
                </button>
              );
            })}
          </div>
        </div>
      </section>

      {result.fetching ? (
        <Loading lines={5} />
      ) : result.error ? (
        <div className="mark-left mb-4 py-2 border-l-2 border-danger pl-md">
          <p className="text-sm px-3 text-danger">
            加载失败：{result.error.message}
          </p>
        </div>
      ) : items.length === 0 ? (
        <Empty title="暂无请假申请" description="当前筛选条件下没有记录" />
      ) : (
        <section>
          <div className="flex items-baseline justify-between mb-4">
            <h2 className="text-xl font-serif text-ink">
              申请列表
              <span className="ml-2 text-sm font-sans text-ink-muted">
                共 {total} 条
              </span>
            </h2>
          </div>
          <div className="rule-thin mb-4" />
          <div className="border border-rule rounded-card overflow-hidden">
            <table className="w-full text-sm">
              <thead className="bg-subtle">
                <tr>
                  <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted">
                    申请人
                  </th>
                  <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted">
                    类型
                  </th>
                  <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted">
                    起止日期
                  </th>
                  <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted">
                    原因
                  </th>
                  <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted">
                    状态
                  </th>
                  <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted">
                    操作
                  </th>
                </tr>
              </thead>
              <tbody>
                {items.map((r) => (
                  <tr key={r.id} className="border-t border-rule">
                    <td className="px-4 py-3">
                      <p className="font-serif text-ink">{r.applicantName}</p>
                      <p className="text-tiny font-mono text-ink-muted">
                        {r.applicantRole}
                      </p>
                    </td>
                    <td className="px-4 py-3 text-sm text-ink">
                      {LEAVE_TYPE_LABEL[r.type]}
                    </td>
                    <td className="px-4 py-3 font-mono text-tiny text-ink-muted">
                      {r.startDate} ~ {r.endDate}
                    </td>
                    <td className="px-4 py-3 text-tiny text-ink-muted max-w-xs">
                      <p className="truncate">{r.reason}</p>
                    </td>
                    <td className="px-4 py-3">
                      <span
                        className={`inline-block px-2 py-0.5 rounded-button text-tiny font-mono border ${statusBadgeClass(
                          r.status,
                        )}`}
                      >
                        {LEAVE_STATUS_LABEL[r.status]}
                      </span>
                    </td>
                    <td className="px-4 py-3">
                      {r.status === "PENDING" ? (
                        <div className="flex items-center gap-2">
                          <button
                            type="button"
                            onClick={() => openReview(r, "APPROVE")}
                            className="text-tiny uppercase tracking-wide text-success hover:opacity-70"
                          >
                            批准
                          </button>
                          <button
                            type="button"
                            onClick={() => openReview(r, "REJECT")}
                            className="text-tiny uppercase tracking-wide text-danger hover:opacity-70"
                          >
                            拒绝
                          </button>
                        </div>
                      ) : (
                        <span className="text-tiny text-ink-muted">
                          {r.reviewedAt
                            ? `${r.reviewerName ?? "—"} · ${r.reviewedAt.slice(
                                0,
                                10,
                              )}`
                            : "—"}
                        </span>
                      )}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>

          {/* 分页 */}
          <div className="mt-6 flex items-center justify-between">
            <button
              type="button"
              onClick={() => setPage((p) => Math.max(1, p - 1))}
              disabled={page <= 1}
              className="px-4 py-2 text-sm text-ink border border-rule rounded-button hover:bg-subtle disabled:opacity-40 disabled:cursor-not-allowed"
            >
              上一页
            </button>
            <span className="text-tiny text-ink-muted">
              第 {page} 页（每页 {pageSize} 条）
            </span>
            <button
              type="button"
              onClick={() => setPage((p) => p + 1)}
              disabled={items.length < pageSize}
              className="px-4 py-2 text-sm text-ink border border-rule rounded-button hover:bg-subtle disabled:opacity-40 disabled:cursor-not-allowed"
            >
              下一页
            </button>
          </div>
        </section>
      )}

      {/* 审批对话框 */}
      {reviewTarget && (
        <div
          className="fixed inset-0 z-50 flex items-center justify-center"
          style={{ background: "hsl(var(--color-ink) / 0.3)" }}
          role="dialog"
          aria-modal="true"
        >
          <div className="w-full max-w-lg p-8 bg-paper border border-rule rounded-card">
            <div className="flex items-baseline justify-between mb-4">
              <h3 className="text-xl font-serif text-ink">
                {reviewAction === "APPROVE" ? "批准请假" : "拒绝请假"}
              </h3>
              <button
                type="button"
                onClick={closeReview}
                className="text-tiny text-ink-muted hover:opacity-70"
              >
                关闭
              </button>
            </div>
            <div className="rule-thin mb-4" />
            <div className="mb-4">
              <p className="text-sm text-ink-muted">
                申请人：<span className="text-ink">
                  {reviewTarget.applicantName}
                </span>
              </p>
              <p className="mt-1 text-sm text-ink-muted">
                类型：
                <span className="text-ink">
                  {LEAVE_TYPE_LABEL[reviewTarget.type]}
                </span>
              </p>
              <p className="mt-1 text-sm text-ink-muted">
                日期：<span className="font-mono text-ink">
                  {reviewTarget.startDate} ~ {reviewTarget.endDate}
                </span>
              </p>
              <p className="mt-2 text-sm text-ink-muted">
                原因：<span className="text-ink">{reviewTarget.reason}</span>
              </p>
            </div>
            <div className="mb-4">
              <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
                审批意见
              </label>
              <textarea
                value={reviewComment}
                onChange={(e) => setReviewComment(e.target.value)}
                rows={3}
                placeholder="可选：填写审批意见"
                className="w-full px-3 py-2 bg-transparent border border-rule rounded-button text-sm text-ink focus:outline-none focus:border-accent"
              />
            </div>
            {reviewError && (
              <p className="mb-3 text-tiny text-danger">{reviewError}</p>
            )}
            <div className="flex items-center justify-end gap-3">
              <button
                type="button"
                onClick={closeReview}
                disabled={submitting}
                className="px-4 py-2 text-sm text-ink border border-rule rounded-button hover:bg-subtle disabled:opacity-50"
              >
                取消
              </button>
              <button
                type="button"
                onClick={handleApprove}
                disabled={submitting}
                className={`px-4 py-2 text-sm text-ink-on-accent rounded-button disabled:opacity-50 hover:opacity-80 ${
                  reviewAction === "APPROVE" ? "bg-success" : "bg-danger"
                }`}
              >
                {submitting
                  ? "处理中..."
                  : reviewAction === "APPROVE"
                    ? "确认批准"
                    : "确认拒绝"}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* 提交请假对话框 */}
      {showSubmit && (
        <div
          className="fixed inset-0 z-50 flex items-center justify-center"
          style={{ background: "hsl(var(--color-ink) / 0.3)" }}
          role="dialog"
          aria-modal="true"
        >
          <div className="w-full max-w-lg p-8 bg-paper border border-rule rounded-card">
            <div className="flex items-baseline justify-between mb-4">
              <h3 className="text-xl font-serif text-ink">提交请假申请</h3>
              <button
                type="button"
                onClick={closeSubmit}
                className="text-tiny text-ink-muted hover:opacity-70"
              >
                关闭
              </button>
            </div>
            <div className="rule-thin mb-4" />
            {formSuccess ? (
              <div className="mb-4 p-4 border border-rule rounded-card bg-subtle">
                <p className="text-sm text-success">{formSuccess}</p>
                <button
                  type="button"
                  onClick={() => setFormSuccess(null)}
                  className="mt-2 text-tiny text-accent hover:opacity-70"
                >
                  再提交一条
                </button>
              </div>
            ) : null}
            <div className="mb-4">
              <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
                类型
              </label>
              <select
                value={formType}
                onChange={(e) => setFormType(e.target.value as LeaveType)}
                className="w-full px-3 py-2 bg-transparent border-b border-rule text-sm font-sans text-ink focus:outline-none focus:border-accent"
              >
                {LEAVE_TYPES.map((t) => (
                  <option key={t.value} value={t.value}>
                    {t.label}
                  </option>
                ))}
              </select>
            </div>
            <div className="mb-4 grid grid-cols-2 gap-4">
              <div>
                <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
                  开始日期
                </label>
                <input
                  type="date"
                  value={formStart}
                  onChange={(e) => setFormStart(e.target.value)}
                  className="w-full px-3 py-2 bg-transparent border-b border-rule text-sm font-sans text-ink focus:outline-none focus:border-accent"
                />
              </div>
              <div>
                <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
                  结束日期
                </label>
                <input
                  type="date"
                  value={formEnd}
                  onChange={(e) => setFormEnd(e.target.value)}
                  className="w-full px-3 py-2 bg-transparent border-b border-rule text-sm font-sans text-ink focus:outline-none focus:border-accent"
                />
              </div>
            </div>
            <div className="mb-4">
              <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
                原因
              </label>
              <textarea
                value={formReason}
                onChange={(e) => setFormReason(e.target.value)}
                rows={3}
                placeholder="请填写请假原因"
                className="w-full px-3 py-2 bg-transparent border border-rule rounded-button text-sm text-ink focus:outline-none focus:border-accent"
              />
            </div>
            {formError && (
              <p className="mb-3 text-tiny text-danger">{formError}</p>
            )}
            <div className="flex items-center justify-end gap-3">
              <button
                type="button"
                onClick={closeSubmit}
                disabled={formSubmitting}
                className="px-4 py-2 text-sm text-ink border border-rule rounded-button hover:bg-subtle disabled:opacity-50"
              >
                关闭
              </button>
              <button
                type="button"
                onClick={handleSubmitLeave}
                disabled={formSubmitting}
                className="px-4 py-2 text-sm text-ink-on-accent bg-accent rounded-button hover:bg-accent-hover disabled:opacity-50"
              >
                {formSubmitting ? "提交中..." : "提交申请"}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
