import type { CustomerRecord } from '../types';
import type {
  CustomerRiskTag,
  MockUser,
  ReviewConclusionCode,
  ReviewCycleOption,
  ReviewStatusCode,
  RiskLevelCode,
  RiskTagApplyForm,
  RiskTagOperationLog,
  RiskTagReviewForm,
  RiskTagsByCustomer,
  TagCategoryCode,
  TagStatusCode,
} from '../types/riskTag';
import {
  HIGH_RISK_LEVELS,
  LEGACY_TAG_ALIASES,
  REVIEW_CONCLUSION_LABELS,
  RISK_LEVEL_LABELS,
  SOURCE_LABELS,
  TAG_CATALOG_MAP,
  TAG_STATUS_LABELS,
} from './riskTagConstants';
import seedOperationLogs from '../data/risk-tag-operation-logs.json';

let idCounter = 1000;

export function nextId(prefix: string): string {
  idCounter += 1;
  return `${prefix}-${idCounter}`;
}

export function formatNow(): string {
  const now = new Date();
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
}

export function todayDate(): string {
  return formatNow().slice(0, 10);
}

function addMonths(dateStr: string, months: number): string {
  const d = new Date(dateStr);
  d.setMonth(d.getMonth() + months);
  return d.toISOString().slice(0, 10);
}

export function parseReviewCycleMonths(cycle: string): number {
  const matched = cycle.match(/^(\d+)/);
  return matched ? Number(matched[1]) : 3;
}

export function nextReviewDateFromCycle(fromDate: string, cycle: ReviewCycleOption | string): string {
  return addMonths(fromDate, parseReviewCycleMonths(cycle));
}

export function isLegalRiskTag(tag: CustomerRiskTag): boolean {
  return tag.tagCategory === 'legal';
}

export function getTaggedAt(tag: CustomerRiskTag): string {
  return tag.taggedAt || tag.effectiveDate;
}

export function getNextReviewAt(tag: CustomerRiskTag): string {
  if (isLegalRiskTag(tag)) return tag.nextReviewAt || tag.expireDate;
  return tag.expireDate;
}

export function computeReviewStatus(tag: CustomerRiskTag): ReviewStatusCode {
  if (!isLegalRiskTag(tag) || tag.status !== 'active') return 'normal';
  const nextReview = getNextReviewAt(tag);
  if (!nextReview) return 'normal';
  const today = todayDate();
  if (nextReview < today) return 'overdue';
  const diffMs = new Date(nextReview).getTime() - new Date(today).getTime();
  if (diffMs <= 7 * 24 * 60 * 60 * 1000) return 'dueSoon';
  return 'normal';
}

export function normalizeRiskTag(tag: CustomerRiskTag): CustomerRiskTag {
  const taggedAt = getTaggedAt(tag);
  const isLegal = isLegalRiskTag(tag);
  const reviewCycle = (tag.reviewCycle || '3个月') as ReviewCycleOption;
  const nextReviewAt = tag.nextReviewAt
    || (isLegal ? tag.expireDate : '')
    || (isLegal ? nextReviewDateFromCycle(taggedAt, reviewCycle) : '');
  const normalized: CustomerRiskTag = {
    ...tag,
    taggedAt,
    effectiveDate: taggedAt,
    reviewCycle,
    nextReviewAt: isLegal ? nextReviewAt : tag.nextReviewAt ?? '',
    expireDate: isLegal ? nextReviewAt : tag.expireDate,
    reviewLogs: tag.reviewLogs ?? [],
  };
  return {
    ...normalized,
    reviewStatus: computeReviewStatus(normalized),
  };
}

export function defaultExpireDate(category: TagCategoryCode, fromDate = todayDate()): string {
  if (category === 'legal') return nextReviewDateFromCycle(fromDate, '3个月');
  if (category === 'finance') return addMonths(fromDate, 1);
  return addMonths(fromDate, 12);
}

export function defaultNextReviewDate(
  category: TagCategoryCode,
  cycle: ReviewCycleOption | string,
  fromDate = todayDate(),
): string {
  if (category === 'legal') return nextReviewDateFromCycle(fromDate, cycle);
  return defaultExpireDate(category, fromDate);
}

export function defaultEffectiveTo(): string {
  return defaultExpireDate('business');
}

export function resolveInitialStatus(riskLevel: RiskLevelCode): TagStatusCode {
  return HIGH_RISK_LEVELS.includes(riskLevel) ? 'pending' : 'active';
}

export function resolveStatusName(status: TagStatusCode): string {
  return TAG_STATUS_LABELS[status];
}

export function resolveRiskLevelName(level: RiskLevelCode): string {
  return RISK_LEVEL_LABELS[level];
}

export function isHighRiskLevel(level: RiskLevelCode): boolean {
  return HIGH_RISK_LEVELS.includes(level);
}

/** @deprecated 法务标签请使用 isLegalReviewDueSoon */
export function isExpiringSoon(tag: CustomerRiskTag, withinDays = 7): boolean {
  return isLegalReviewDueSoon(tag, withinDays);
}

export function isLegalReviewDueSoon(tag: CustomerRiskTag, withinDays = 7): boolean {
  if (tag.status !== 'active' || !isLegalRiskTag(tag)) return false;
  const today = todayDate();
  const nextReview = getNextReviewAt(tag);
  if (!nextReview || nextReview <= today) return false;
  const diffMs = new Date(nextReview).getTime() - new Date(today).getTime();
  return diffMs <= withinDays * 24 * 60 * 60 * 1000;
}

export function isLegalReviewOverdue(tag: CustomerRiskTag): boolean {
  if (!isLegalRiskTag(tag) || tag.status !== 'active') return false;
  const nextReview = getNextReviewAt(tag);
  return Boolean(nextReview && nextReview < todayDate());
}

/** @deprecated 法务标签请使用 isLegalReviewOverdue */
export function isReviewOverdue(tag: CustomerRiskTag): boolean {
  return isLegalReviewOverdue(tag);
}

export function getDisplayStatusName(tag: CustomerRiskTag): string {
  const normalized = normalizeRiskTag(tag);
  if (isLegalRiskTag(normalized) && normalized.reviewStatus === 'overdue') return '待复核';
  if (normalized.removalRequested && normalized.status === 'active') return '解除待审批';
  return normalized.statusName;
}

export function buildTagFromCatalog(
  customerId: string,
  tagName: string,
  partial?: Partial<CustomerRiskTag>,
): CustomerRiskTag | null {
  const resolvedName = LEGACY_TAG_ALIASES[tagName] ?? tagName;
  const catalog = TAG_CATALOG_MAP[resolvedName];
  if (!catalog) return null;

  const createdAt = partial?.createdAt ?? formatNow();
  const taggedAt = partial?.taggedAt ?? partial?.effectiveDate ?? createdAt.slice(0, 10);
  const reviewCycle = (partial?.reviewCycle ?? catalog.reviewCycle) as ReviewCycleOption;
  const isLegal = catalog.tagCategory === 'legal';
  const nextReviewAt = partial?.nextReviewAt
    ?? (isLegal ? partial?.expireDate : undefined)
    ?? (isLegal ? nextReviewDateFromCycle(taggedAt, reviewCycle) : '');
  const expireDate = partial?.expireDate
    ?? (isLegal ? nextReviewAt : defaultExpireDate(catalog.tagCategory, taggedAt));
  const status = partial?.status ?? 'active';
  const riskLevel = partial?.riskLevel ?? catalog.defaultLevel;

  return normalizeRiskTag({
    id: partial?.id ?? nextId('tag'),
    customerId,
    tagCode: catalog.tagCode,
    tagName: catalog.tagName,
    tagCategory: catalog.tagCategory,
    tagCategoryName: catalog.tagCategoryName,
    responsibleDept: catalog.responsibleDept,
    editableRoles: catalog.editableRoles,
    riskLevel,
    riskLevelName: resolveRiskLevelName(riskLevel),
    status,
    statusName: resolveStatusName(status),
    source: partial?.source ?? 'system',
    sourceName: partial?.source === 'manual' ? SOURCE_LABELS.manual : SOURCE_LABELS.system,
    reason: partial?.reason ?? '历史数据迁移：列表既有标签自动建档',
    taggedAt,
    effectiveDate: taggedAt,
    expireDate,
    nextReviewAt: isLegal ? nextReviewAt : '',
    reviewCycle,
    lastReviewedAt: partial?.lastReviewedAt,
    reviewLogs: partial?.reviewLogs ?? [],
    createdBy: partial?.createdBy ?? '系统',
    createdAt,
    approvedBy: partial?.approvedBy,
    approvedAt: partial?.approvedAt,
    attachments: partial?.attachments ?? [],
    sensitiveLevel: catalog.sensitiveLevel,
    financeDetail: partial?.financeDetail,
    rejectReason: partial?.rejectReason,
    removalRequested: partial?.removalRequested,
    removedAt: partial?.removedAt,
    removeReason: partial?.removeReason,
  });
}

export function buildSeedRiskTags(records: CustomerRecord[]): RiskTagsByCustomer {
  const map: RiskTagsByCustomer = {};

  records.forEach((record) => {
    if (!record.labels.length) return;

    map[record.id] = record.labels
      .map((tagName, index) =>
        buildTagFromCatalog(record.id, tagName, {
          id: `seed-${record.id}-${index}`,
          createdAt: record.createTime,
          taggedAt: record.createTime.slice(0, 10),
          nextReviewAt: record.id === '4' && (tagName === '涉诉/仲裁' || tagName === '资质存疑')
            ? '2024-01-01'
            : undefined,
          source: 'system',
          financeDetail:
            tagName === '严重拖欠' || tagName === '逾期预警'
              ? {
                  overdueAmount: tagName === '严重拖欠' ? '128.6万元' : '32.5万元',
                  billNo: `AR-${record.code}-2024`,
                  receivableNote: '应收明细仅财务授权角色可见',
                }
              : undefined,
          attachments:
            tagName === '涉诉/仲裁' || tagName === '制裁/高风险地区'
              ? [{
                  id: `att-seed-${record.id}-${index}`,
                  name: '诉讼材料摘要.pdf',
                  size: '256 KB',
                  uploadedAt: record.createTime,
                  attachmentType: 'legal',
                }]
              : [],
        }),
      )
      .filter((tag): tag is CustomerRiskTag => Boolean(tag));
  });

  return map;
}

export function syncRecordLabels(
  records: CustomerRecord[],
  riskTagsByCustomer: RiskTagsByCustomer,
): CustomerRecord[] {
  return records.map((record) => ({
    ...record,
    labels: (riskTagsByCustomer[record.id] ?? [])
      .filter((tag) => tag.status === 'active' && !tag.removalRequested)
      .map((tag) => tag.tagName),
  }));
}

export function getActiveTags(tags: CustomerRiskTag[]): CustomerRiskTag[] {
  return tags.filter((tag) => tag.status === 'active');
}

export function getPendingTags(tags: CustomerRiskTag[]): CustomerRiskTag[] {
  return tags.filter((tag) => tag.status === 'pending');
}

export function getVisibleListTags(tags: CustomerRiskTag[]): CustomerRiskTag[] {
  return tags.filter(
    (tag) =>
      tag.status === 'active'
      || tag.status === 'pending'
      || (tag.status === 'active' && tag.removalRequested),
  );
}

export function createOperationLog(
  partial: Omit<RiskTagOperationLog, 'id' | 'createdAt'>,
): RiskTagOperationLog {
  return {
    ...partial,
    id: nextId('log'),
    createdAt: formatNow(),
  };
}

export function buildApplyTag(
  customerId: string,
  form: RiskTagApplyForm,
  user: MockUser,
): CustomerRiskTag | null {
  const catalog = TAG_CATALOG_MAP[form.tagName];
  if (!catalog) return null;

  const now = formatNow();
  const riskLevel = form.riskLevel || catalog.defaultLevel;
  const status = resolveInitialStatus(riskLevel);
  const taggedAt = form.taggedAt || form.effectiveDate || todayDate();
  const isLegal = catalog.tagCategory === 'legal';
  const reviewCycle = form.reviewCycle || (catalog.reviewCycle as ReviewCycleOption);
  const nextReviewAt = isLegal
    ? (form.nextReviewAt || nextReviewDateFromCycle(taggedAt, reviewCycle))
    : '';
  const expireDate = isLegal
    ? nextReviewAt
    : (form.expireDate || defaultExpireDate(catalog.tagCategory, taggedAt));

  return normalizeRiskTag({
    id: nextId('tag'),
    customerId,
    tagCode: catalog.tagCode,
    tagName: catalog.tagName,
    tagCategory: catalog.tagCategory,
    tagCategoryName: catalog.tagCategoryName,
    responsibleDept: catalog.responsibleDept,
    editableRoles: catalog.editableRoles,
    riskLevel,
    riskLevelName: resolveRiskLevelName(riskLevel),
    status,
    statusName: resolveStatusName(status),
    source: 'manual',
    sourceName: SOURCE_LABELS.manual,
    reason: form.reason.trim(),
    taggedAt,
    effectiveDate: taggedAt,
    expireDate,
    nextReviewAt,
    reviewCycle,
    reviewLogs: [],
    createdBy: user.name,
    createdAt: now,
    attachments: form.attachments,
    sensitiveLevel: catalog.sensitiveLevel,
    financeDetail:
      catalog.sensitiveLevel === 'financeSensitive'
        ? { overdueAmount: '待财务录入', billNo: '—', receivableNote: '新增后由财务补充明细' }
        : undefined,
  });
}

export function buildApplyLog(
  tag: CustomerRiskTag,
  customerName: string,
  user: MockUser,
  batchCount?: number,
): RiskTagOperationLog {
  const action = tag.status === 'pending' ? '提交审批' : batchCount && batchCount > 1 ? '批量打标' : '新增标签';
  const statusAfter = tag.statusName;
  const reason = batchCount && batchCount > 1
    ? `批量为 ${batchCount} 个客户提交标签「${tag.tagName}」`
    : `提交标签「${tag.tagName}」，原因：${tag.reason}`;

  return createOperationLog({
    customerId: tag.customerId,
    customerName,
    tagId: tag.id,
    tagName: tag.tagName,
    tagCategory: tag.tagCategory,
    tagCategoryName: tag.tagCategoryName,
    action,
    reason,
    statusBefore: '—',
    statusAfter,
    operator: user.name,
    operatorRole: user.role,
    detail: reason,
  });
}

export function buildRemoveLog(
  tag: CustomerRiskTag,
  customerName: string,
  user: MockUser,
  reason: string,
  isApplication = false,
): RiskTagOperationLog {
  return createOperationLog({
    customerId: tag.customerId,
    customerName,
    tagId: tag.id,
    tagName: tag.tagName,
    tagCategory: tag.tagCategory,
    tagCategoryName: tag.tagCategoryName,
    action: isApplication ? '提交审批' : '解除标签',
    reason: isApplication ? `申请解除标签，原因：${reason}` : `解除标签，原因：${reason}`,
    statusBefore: getDisplayStatusName(tag),
    statusAfter: isApplication ? '解除待审批' : TAG_STATUS_LABELS.removed,
    operator: user.name,
    operatorRole: user.role,
    detail: reason,
  });
}

export function buildApprovalLog(
  tag: CustomerRiskTag,
  customerName: string,
  user: MockUser,
  approved: boolean,
  rejectReason?: string,
): RiskTagOperationLog {
  return createOperationLog({
    customerId: tag.customerId,
    customerName,
    tagId: tag.id,
    tagName: tag.tagName,
    tagCategory: tag.tagCategory,
    tagCategoryName: tag.tagCategoryName,
    action: approved ? '审批通过' : '审批驳回',
    reason: approved
      ? `审批通过标签「${tag.tagName}」`
      : `驳回标签「${tag.tagName}」${rejectReason ? `：${rejectReason}` : ''}`,
    statusBefore: TAG_STATUS_LABELS.pending,
    statusAfter: approved ? TAG_STATUS_LABELS.active : TAG_STATUS_LABELS.rejected,
    operator: user.name,
    operatorRole: user.role,
    detail: rejectReason,
  });
}

export function buildRemovalApprovalLog(
  tag: CustomerRiskTag,
  customerName: string,
  user: MockUser,
  approved: boolean,
  rejectReason?: string,
): RiskTagOperationLog {
  return createOperationLog({
    customerId: tag.customerId,
    customerName,
    tagId: tag.id,
    tagName: tag.tagName,
    tagCategory: tag.tagCategory,
    tagCategoryName: tag.tagCategoryName,
    action: approved ? '审批通过' : '审批驳回',
    reason: approved
      ? `解除申请已通过，标签「${tag.tagName}」已解除`
      : `驳回解除申请「${tag.tagName}」${rejectReason ? `：${rejectReason}` : ''}`,
    statusBefore: '解除待审批',
    statusAfter: approved ? TAG_STATUS_LABELS.removed : TAG_STATUS_LABELS.active,
    operator: user.name,
    operatorRole: user.role,
    detail: rejectReason,
  });
}

export function buildReviewLog(
  tag: CustomerRiskTag,
  customerName: string,
  user: MockUser,
  conclusion: ReviewConclusionCode,
  note: string,
  nextReviewAt?: string,
): RiskTagOperationLog {
  const conclusionName = REVIEW_CONCLUSION_LABELS[conclusion];
  const maintain = conclusion !== 'riskResolved';
  return createOperationLog({
    customerId: tag.customerId,
    customerName,
    tagId: tag.id,
    tagName: tag.tagName,
    tagCategory: tag.tagCategory,
    tagCategoryName: tag.tagCategoryName,
    action: '到期复核',
    reason: maintain
      ? `完成复核：${conclusionName}。${note}${nextReviewAt ? `；下次复核 ${nextReviewAt}` : ''}`
      : `完成复核：${conclusionName}，提交解除申请。${note}`,
    statusBefore: getDisplayStatusName(tag),
    statusAfter: maintain ? '生效中' : '解除待审批',
    operator: user.name,
    operatorRole: user.role,
    detail: note,
  });
}

export function hasDuplicateActiveTag(tags: CustomerRiskTag[], tagName: string): boolean {
  return tags.some(
    (tag) =>
      tag.tagName === tagName
      && (tag.status === 'active' || tag.status === 'pending'),
  );
}

export const INITIAL_OPERATION_LOGS = (seedOperationLogs as RiskTagOperationLog[]).map((log) => ({
  ...log,
  tagCategory: log.tagCategory ?? 'finance',
  tagCategoryName: log.tagCategoryName ?? '财务风险',
  reason: log.reason ?? log.detail ?? '',
  statusBefore: log.statusBefore ?? '—',
  statusAfter: log.statusAfter ?? '—',
}));

export function catalogDefaultsForTag(tagName: string): Pick<RiskTagApplyForm, 'tagCategory' | 'riskLevel'> {
  const catalog = TAG_CATALOG_MAP[tagName];
  if (!catalog) {
    return { tagCategory: 'legal', riskLevel: 'medium' };
  }
  return { tagCategory: catalog.tagCategory, riskLevel: catalog.defaultLevel };
}

export function validateApplyForm(form: RiskTagApplyForm): string | null {
  if (!form.tagName.trim()) return '请选择标签名称';
  if (!form.tagCategory) return '请选择标签类型';
  if (!form.riskLevel) return '请选择风险级别';
  if (!form.reason.trim()) return '请填写原因说明';
  if (form.reason.trim().length < 10) return '原因说明至少 10 个字';

  const taggedAt = form.taggedAt || form.effectiveDate;
  if (!taggedAt) return '请选择打标时间';

  if (form.tagCategory === 'legal') {
    if (!form.reviewCycle) return '请选择复核周期';
    if (!form.nextReviewAt) return '请选择下次复核时间';
    if (form.nextReviewAt < taggedAt) return '下次复核时间不能早于打标时间';
  } else {
    if (!form.expireDate) return '请选择有效期至';
    if (form.expireDate < taggedAt) return '有效期不能早于打标时间';
  }

  if (isHighRiskLevel(form.riskLevel) && form.attachments.length === 0) {
    return '高风险和致命标签必须上传附件';
  }
  return null;
}

export function validateReviewForm(form: RiskTagReviewForm): string | null {
  if (!form.note.trim()) return '请填写复核说明';
  if (form.note.trim().length < 5) return '复核说明至少 5 个字';
  if (form.conclusion === 'riskResolved') {
    if (!form.removeReason.trim()) return '请填写解除原因';
    if (form.removeReason.trim().length < 5) return '解除原因至少 5 个字';
    return null;
  }
  if (!form.nextReviewAt) return '请选择下次复核时间';
  if (form.nextReviewAt < todayDate()) return '下次复核时间不能早于今天';
  return null;
}

export function legalTagsNeedReview(tags: CustomerRiskTag[]): CustomerRiskTag[] {
  return tags
    .map(normalizeRiskTag)
    .filter((tag) => isLegalRiskTag(tag) && tag.reviewStatus === 'overdue');
}

/** @deprecated 请使用 legalTagsNeedReview */
export function tagsNeedReview(tags: CustomerRiskTag[]): CustomerRiskTag[] {
  return legalTagsNeedReview(tags);
}

export function groupTagsByCategory(tags: CustomerRiskTag[]): Record<TagCategoryCode, CustomerRiskTag[]> {
  const groups: Record<TagCategoryCode, CustomerRiskTag[]> = {
    legal: [],
    finance: [],
    business: [],
  };
  tags
    .map(normalizeRiskTag)
    .filter((tag) => tag.status !== 'removed' && tag.status !== 'rejected')
    .forEach((tag) => {
      if (groups[tag.tagCategory]) {
        groups[tag.tagCategory].push(tag);
      }
    });
  return groups;
}

export function triggersBlacklistHint(tagName: string): boolean {
  const catalog = TAG_CATALOG_MAP[tagName];
  return catalog?.triggersBlacklist ?? false;
}

export function buildWorkbenchTodoLog(
  tag: CustomerRiskTag,
  customerName: string,
): RiskTagOperationLog {
  return createOperationLog({
    customerId: tag.customerId,
    customerName,
    tagId: tag.id,
    tagName: tag.tagName,
    tagCategory: tag.tagCategory,
    tagCategoryName: tag.tagCategoryName,
    action: '工作台待办',
    reason: `已向法务工作台发起待办：请查验客户「${customerName}」的法务标签「${tag.tagName}」，查验后如需解除请在本页申请解除。`,
    statusBefore: '待复核',
    statusAfter: '待办已推送',
    operator: '系统',
    operatorRole: 'admin',
    detail: `下次复核时间 ${tag.nextReviewAt || '—'}`,
  });
}

export function createReviewLogEntry(
  user: MockUser,
  form: RiskTagReviewForm,
): NonNullable<CustomerRiskTag['reviewLogs']>[number] {
  return {
    id: nextId('rev'),
    reviewedAt: formatNow(),
    reviewedBy: user.name,
    conclusion: form.conclusion,
    conclusionName: REVIEW_CONCLUSION_LABELS[form.conclusion],
    note: form.note.trim(),
    nextReviewAt: form.conclusion === 'riskResolved' ? undefined : form.nextReviewAt,
    attachments: form.attachments,
  };
}
