import { useCallback, useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Button,
  Empty,
  Input,
  message,
  Modal,
  Space,
  Spin,
  Table,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { UserOutlined } from '@ant-design/icons';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { getTaskScoreDetail, saveTaskUserScore } from '@/api/appraisal';
import PageBackButton from '@/components/PageBackButton';
import './appraisal-detail.css';

interface DetailItem {
  _rowKey?: string;
  id?: string | number;
  reviewCategory?: string;
  reviewItem?: string;
  remarks?: string;
  score?: number;
  weight?: number;
  remark?: string;
  [key: string]: unknown;
}

interface GroupRow {
  category: string;
  items: DetailItem[];
  remarkCate: string;
}

interface ExamineTask {
  taskName?: string;
  templateId?: string | number;
  templateType?: string | number;
}

interface ExamineUser {
  id?: string | number;
  userName?: string;
  manageScore?: string | number;
  judgeContent?: string;
  selfJudgeContent?: string;
  examineStatus?: string | number;
  examineStatusSelf?: string | number;
}

interface RemarkRow {
  remark?: string;
}

const isObject = (value: unknown): value is Record<string, unknown> =>
  typeof value === 'object' && value !== null;

const toNumber = (value: unknown, fallback = 0) => {
  const num = Number(value);
  return Number.isFinite(num) ? num : fallback;
};

const clampScore = (value: number) => Math.min(10, Math.max(0, Math.round(value)));

const toBoolean = (value: unknown) => {
  if (typeof value === 'boolean') {
    return value;
  }
  if (typeof value === 'number') {
    return value === 1;
  }
  const raw = String(value ?? '').toLowerCase().trim();
  return raw === '1' || raw === 'true' || raw === 'yes';
};

const normalizePayload = (response: unknown) =>
  isObject(response) && response.data !== undefined ? response.data : response;

const groupDetailRows = (items: DetailItem[], remarks: RemarkRow[] = []) => {
  const map = new Map<string, DetailItem[]>();
  items.forEach((item) => {
    const key = String(item.reviewCategory ?? '未分类');
    const list = map.get(key) ?? [];
    const fallbackKey = `${key}_${list.length}`;
    list.push({
      ...item,
      _rowKey: String(item.id ?? fallbackKey),
      score: toNumber(item.score, 0),
      weight: toNumber(item.weight, 0),
      remark: String(item.remark ?? ''),
    });
    map.set(key, list);
  });

  const groups: GroupRow[] = [];
  Array.from(map.entries()).forEach(([category, list], index) => {
    groups.push({
      category,
      items: list,
      remarkCate: String(remarks[index]?.remark ?? ''),
    });
  });
  return groups;
};

interface ScoreBarProps {
  value: number;
  editable: boolean;
  onChange: (value: number) => void;
}

const ScoreBar = ({ value, editable, onChange }: ScoreBarProps) => {
  const normalized = clampScore(value);

  const updateByPercent = (percent: number) => {
    onChange(clampScore(percent * 10));
  };

  const handleTrackClick = (event: React.MouseEvent<HTMLDivElement>) => {
    if (!editable) {
      return;
    }
    const rect = event.currentTarget.getBoundingClientRect();
    if (rect.width <= 0) {
      return;
    }
    const percent = (event.clientX - rect.left) / rect.width;
    updateByPercent(percent);
  };

  const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
    if (!editable) {
      return;
    }
    if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {
      event.preventDefault();
      onChange(clampScore(normalized - 1));
      return;
    }
    if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {
      event.preventDefault();
      onChange(clampScore(normalized + 1));
    }
  };

  const bubblePosition = normalized * 10;
  const bubbleClass =
    normalized === 0 ? 'detail-score-bubble is-start' : normalized === 10 ? 'detail-score-bubble is-end' : 'detail-score-bubble';

  return (
    <div className="detail-score-wrap">
      <div className="detail-score-top">
        <span>0</span>
      </div>
      <div
        className={`detail-score-track ${editable ? 'is-editable' : 'is-readonly'}`}
        onClick={handleTrackClick}
        role={editable ? 'slider' : undefined}
        aria-valuemin={0}
        aria-valuemax={10}
        aria-valuenow={normalized}
        tabIndex={editable ? 0 : -1}
        onKeyDown={handleKeyDown}
      >
        <div className="detail-score-fill" style={{ width: `${bubblePosition}%` }} />
        <div className={bubbleClass} style={{ left: `${bubblePosition}%` }}>
          {normalized}
        </div>
      </div>
      {normalized === 0 && <div className="statusText">暂未打分</div>}
    </div>
  );
};

const AppraisalDetailPage = () => {
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();

  const isNormal = toBoolean(searchParams.get('isNormal'));
  const [isEdit, setIsEdit] = useState(toBoolean(searchParams.get('edit')));
  const examineTaskId = searchParams.get('examineTaskId') ?? searchParams.get('taskId') ?? '';
  const reviewType = searchParams.get('reviewType') ?? (isNormal ? '1' : '0');
  const routeExamineId = searchParams.get('examineId') ?? '';
  const routeUserId = searchParams.get('userId') ?? '';

  const [loading, setLoading] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [examineTask, setExamineTask] = useState<ExamineTask>({});
  const [examineUser, setExamineUser] = useState<ExamineUser>({});
  const [groups, setGroups] = useState<GroupRow[]>([]);
  const [manageScore, setManageScore] = useState<number>(0);
  const [judgeContent, setJudgeContent] = useState('');

  const [remarkModalOpen, setRemarkModalOpen] = useState(false);
  const [editingCell, setEditingCell] = useState<{ groupIndex: number; rowIndex: number } | null>(null);
  const [remarkDraft, setRemarkDraft] = useState('');

  const templateType = useMemo(() => String(examineTask.templateType ?? ''), [examineTask.templateType]);
  const isTemplateZero = templateType === '0';

  const recalcManageScore = useCallback((nextGroups: GroupRow[]) => {
    const score = nextGroups
      .flatMap((group) => group.items)
      .reduce((sum, row) => sum + toNumber(row.score) * toNumber(row.weight), 0) / 10;
    setManageScore(Number(score.toFixed(2)));
  }, []);

  const loadDetail = useCallback(async () => {
    if (!examineTaskId) {
      return;
    }

    setLoading(true);
    try {
      const params: Record<string, unknown> = {
        examineTaskId,
        reviewType,
      };
      if (routeExamineId) {
        params.examineId = routeExamineId;
      }
      if (routeUserId) {
        params.userId = routeUserId;
      }

      const response = await getTaskScoreDetail(params);
      const payload = normalizePayload(response);

      if (!isObject(payload)) {
        message.error('评分详情返回格式异常');
        setGroups([]);
        return;
      }

      const detailRows = Array.isArray(payload.examineConfigDetailVoList)
        ? (payload.examineConfigDetailVoList as DetailItem[])
        : [];
      const remarks = Array.isArray(payload.remark) ? (payload.remark as RemarkRow[]) : [];
      const nextGroups = groupDetailRows(detailRows, remarks);
      setGroups(nextGroups);

      const task = isObject(payload.examineTask) ? (payload.examineTask as ExamineTask) : {};
      const user = isObject(payload.examineUser) ? (payload.examineUser as ExamineUser) : {};
      setExamineTask(task);
      setExamineUser(user);

      if (isNormal && String(task.templateType ?? '') === '0') {
        setJudgeContent(String(user.selfJudgeContent ?? user.judgeContent ?? ''));
      } else {
        setJudgeContent(String(user.judgeContent ?? ''));
      }

      const currentManageScore = toNumber(user.manageScore);
      if (currentManageScore > 0) {
        setManageScore(currentManageScore);
      } else if (!isNormal) {
        recalcManageScore(nextGroups);
      }

      if (String(user.examineStatusSelf ?? '') === '1' && String(user.examineStatus ?? '') === '1') {
        setIsEdit(false);
      }
    } catch (error) {
      console.error('Failed to fetch score detail:', error);
      message.error('获取评分详情失败');
      setGroups([]);
    } finally {
      setLoading(false);
    }
  }, [examineTaskId, isNormal, recalcManageScore, reviewType, routeExamineId, routeUserId]);

  useEffect(() => {
    void loadDetail();
  }, [loadDetail]);

  const updateItemScore = (groupIndex: number, rowIndex: number, value: number) => {
    setGroups((prev) => {
      const next = prev.map((group, gIndex) => {
        if (gIndex !== groupIndex) {
          return group;
        }
        return {
          ...group,
          items: group.items.map((row, rIndex) => (rIndex === rowIndex ? { ...row, score: value } : row)),
        };
      });
      if (!isNormal) {
        recalcManageScore(next);
      }
      return next;
    });
  };

  const updateGroupRemark = (groupIndex: number, value: string) => {
    setGroups((prev) =>
      prev.map((group, idx) =>
        idx === groupIndex
          ? {
              ...group,
              remarkCate: value,
            }
          : group,
      ),
    );
  };

  const openRemarkModal = (groupIndex: number, rowIndex: number) => {
    const row = groups[groupIndex]?.items[rowIndex];
    setEditingCell({ groupIndex, rowIndex });
    setRemarkDraft(String(row?.remark ?? ''));
    setRemarkModalOpen(true);
  };

  const saveRemarkModal = () => {
    if (!editingCell) {
      setRemarkModalOpen(false);
      return;
    }
    if (remarkDraft.length > 200) {
      message.warning('自评总结限制200个字符');
      return;
    }
    setGroups((prev) =>
      prev.map((group, gIndex) => {
        if (gIndex !== editingCell.groupIndex) {
          return group;
        }
        return {
          ...group,
          items: group.items.map((row, rIndex) =>
            rIndex === editingCell.rowIndex
              ? {
                  ...row,
                  remark: remarkDraft,
                }
              : row,
          ),
        };
      }),
    );
    setRemarkModalOpen(false);
  };

  const buildPayload = (submitStatus: 0 | 1) => {
    const allItems = groups.flatMap((group) => group.items);
    const detailList = allItems.map((item) => ({
      score: toNumber(item.score, 0),
      configId: item.id,
      remark: String(item.remark ?? ''),
      reviewCategory: item.reviewCategory,
    }));

    const payload: Record<string, unknown> = {
      examineId: examineUser.id ?? routeExamineId ?? '',
      taskId: examineTaskId,
      reviewType,
      examineDetailList: detailList,
      examineRemarkList: [],
      manageScore: manageScore,
      judgeContent,
    };

    if (isNormal) {
      payload.examineStatusSelf = submitStatus;
    } else {
      payload.examineStatus = submitStatus;
    }

    if (isNormal && !isTemplateZero) {
      payload.examineRemarkList = groups
        .filter((group) => group.category !== '发展与协作')
        .map((group) => ({
          reviewCategory: group.category,
          remark: group.remarkCate,
        }));
    }

    if (isNormal && isTemplateZero) {
      payload.selfJudgeContent = judgeContent;
      payload.judgeContent = '';
    }

    return payload;
  };

  const validateSubmit = (submitStatus: 0 | 1) => {
    if (submitStatus === 0) {
      return true;
    }

    const allItems = groups.flatMap((group) => group.items);
    const hasUnscored = allItems.some(
      (item) => !toNumber(item.score, 0) && (!isNormal || item.reviewCategory !== '发展与协作'),
    );
    if (hasUnscored) {
      message.warning('存在未评分绩效项，请完善后再试');
      return false;
    }

    if (isNormal) {
      const devRows = allItems.filter((item) => item.reviewCategory === '发展与协作');
      const hasEmptyDevRemark = devRows.some((item) => !String(item.remark ?? '').trim());
      if (hasEmptyDevRemark) {
        message.warning('发展与协作下的自评总结为必填，请完善后再试');
        return false;
      }
      const hasShortDevRemark = devRows.some(
        (item) => String(item.remark ?? '').trim().length > 0 && String(item.remark ?? '').trim().length < 100,
      );
      if (hasShortDevRemark) {
        message.warning('发展与协作下的自评总结最少100个字符，请完善后再试');
        return false;
      }
    }

    if (!isNormal && isTemplateZero && judgeContent.length > 300) {
      message.warning('总体评价限制300个字符');
      return false;
    }

    if (!isNormal && !judgeContent.trim()) {
      message.warning('总体评价为必填');
      return false;
    }

    if (isNormal && isTemplateZero && !judgeContent.trim()) {
      message.warning('个人总体评价为必填');
      return false;
    }

    if (isNormal && !isTemplateZero) {
      const cateRemarks = groups.filter((group) => group.category !== '发展与协作').map((group) => group.remarkCate);
      if (cateRemarks.some((remark) => !String(remark).trim())) {
        message.warning('存在未填写大类评价，请完善后再试');
        return false;
      }
      if (cateRemarks.some((remark) => String(remark).trim().length < 100)) {
        message.warning('大类评价最少100个字符，请完善后再试');
        return false;
      }
    }

    return true;
  };

  const submitScore = async (submitStatus: 0 | 1) => {
    if (!validateSubmit(submitStatus)) {
      return;
    }

    const doSubmit = async () => {
      setSubmitting(true);
      try {
        const payload = buildPayload(submitStatus);
        await saveTaskUserScore(payload);
        message.success('操作成功');
        navigate(-1);
      } catch (error) {
        console.error('Failed to save score:', error);
        message.error('保存失败');
      } finally {
        setSubmitting(false);
      }
    };

    if (submitStatus === 1) {
      Modal.confirm({
        title: '确认提交绩效评分',
        content: '提交后将无法修改，该操作不可逆，请确认后再试',
        okText: '确定',
        cancelText: '取消',
        onOk: doSubmit,
      });
      return;
    }

    await doSubmit();
  };

  const buildColumns = (group: GroupRow, groupIndex: number): ColumnsType<DetailItem> => {
    const cols: ColumnsType<DetailItem> = [
      {
        title: '考核项',
        dataIndex: 'reviewItem',
        width: 200,
      },
      {
        title: '评分标准',
        dataIndex: 'remarks',
      },
    ];

    if (!isNormal && examineTask.templateId && group.category === '发展与协作' && !isTemplateZero) {
      cols.push({
        title: '员工自评',
        dataIndex: 'remark',
        render: (_, row) => <Input.TextArea value={String(row.remark ?? '')} autoSize={{ minRows: 3 }} readOnly />,
      });
    }

    if ((isNormal && group.category !== '发展与协作') || !isNormal) {
      cols.push({
        title: '评分',
        dataIndex: 'score',
        width: 380,
        render: (_, row, rowIndex) => (
          <ScoreBar
            value={toNumber(row.score, 0)}
            editable={isEdit}
            onChange={(nextScore) => updateItemScore(groupIndex, rowIndex, nextScore)}
          />
        ),
      });
    }

    if (isNormal && ((examineTask.templateId && group.category === '发展与协作') || !examineTask.templateId)) {
      cols.push({
        title: '自评总结',
        dataIndex: 'remark',
        width: 140,
        render: (_, row, rowIndex) => (
          <Button type="link" onClick={() => openRemarkModal(groupIndex, rowIndex)}>
            {String(row.remark ?? '').trim() ? '查看' : '暂未评价'}
          </Button>
        ),
      });
    }

    return cols;
  };

  return (
    <div className="app-container appraisal-detail-page">
      {!examineTaskId && <Alert type="warning" showIcon message="缺少 examineTaskId 参数，无法加载评分详情" />}

      <Spin spinning={loading}>
        <div className="conetentBox">
          <div style={{ marginBottom: 12 }}>
            <PageBackButton
              fallbackPath={isNormal ? '/workAppraisal/normalWorker' : '/workAppraisal/manager'}
            />
          </div>
          <div className="titleBox">
            <div className="titleMain">
              <span className="block" />
              <span>{examineTask.taskName ?? '绩效考核详情'}</span>
            </div>
            {isEdit && (
              <Space size={20}>
                <Button style={{ width: 90 }} onClick={() => submitScore(0)} loading={submitting}>
                  保存
                </Button>
                <Button style={{ width: 90 }} type="primary" onClick={() => submitScore(1)} loading={submitting}>
                  提交
                </Button>
              </Space>
            )}
          </div>

          <div className="headerBox">
            <div className="userInfo">
              <UserOutlined />
              <span>{examineUser.userName ?? '-'}</span>
            </div>
            {!isNormal && (
              <div className="totalBox">
                <span>考核评分：</span>
                <span className="scoreTotal">{manageScore}</span>
              </div>
            )}
          </div>

          <div className="tableBox">
            {groups.length === 0 ? (
              <Empty description="暂无评分项" />
            ) : (
              groups.map((group, groupIndex) => (
                <div className="tableRow detail-group" key={`${group.category}_${groupIndex}`}>
                  <div className="userBox detail-group-title">{group.category}</div>
                  <Table<DetailItem>
                    rowKey="_rowKey"
                    columns={buildColumns(group, groupIndex)}
                    dataSource={group.items}
                    pagination={false}
                    size="middle"
                  />

                  {isNormal && !isTemplateZero && group.category !== '发展与协作' && (
                    <div className="detail-group-remark">
                      <div className="detail-subtitle">评价</div>
                      <Input.TextArea
                        autoSize={{ minRows: 4 }}
                        maxLength={300}
                        showCount
                        value={group.remarkCate}
                        onChange={(event) => updateGroupRemark(groupIndex, event.target.value)}
                        readOnly={!isEdit}
                        placeholder="0/300"
                      />
                    </div>
                  )}
                </div>
              ))
            )}

            {((isNormal && isTemplateZero) || !isNormal) && (
              <div className="detail-overall">
                <div className="userBox detail-group-title">总体评价</div>
                <Input.TextArea
                  autoSize={{ minRows: 4 }}
                  maxLength={300}
                  showCount
                  value={judgeContent}
                  onChange={(event) => setJudgeContent(event.target.value)}
                  readOnly={!isEdit}
                  placeholder="0/300"
                />
              </div>
            )}
          </div>
        </div>
      </Spin>

      <Modal
        title="自评总结"
        open={remarkModalOpen}
        onOk={isEdit ? saveRemarkModal : () => setRemarkModalOpen(false)}
        onCancel={() => setRemarkModalOpen(false)}
        okButtonProps={{ style: { display: isEdit ? 'inline-flex' : 'none' } }}
        okText="确定"
        cancelText={isEdit ? '取消' : '关闭'}
      >
        <Input.TextArea
          autoSize={{ minRows: 4 }}
          maxLength={200}
          showCount
          value={remarkDraft}
          onChange={(event) => setRemarkDraft(event.target.value)}
          readOnly={!isEdit}
          placeholder="0/200"
        />
      </Modal>
    </div>
  );
};

export default AppraisalDetailPage;
