import React, { useMemo, useRef } from 'react';

import { Upload, X } from 'lucide-react';

import type {

  MockUser,

  RiskLevelCode,

  RiskTagApplyForm,

  RiskTagAttachment,

  RiskTagReviewForm,

  TagCategoryCode,

} from '../types/riskTag';

import {

  REVIEW_CONCLUSION_LABELS,

  REVIEW_CYCLE_OPTIONS,

  RISK_LEVEL_LABELS,

  TAG_CATEGORY_META,

  TAG_CATALOG_MAP,

  TAG_GROUPS,

  tagsForCategory,

} from '../utils/riskTagConstants';

import {

  canAddRiskTags,

  canApplyRiskTag,

  roleLabel,

  roleToTagCategory,

  selectableCategoriesForRole,

} from '../utils/permissions';

import {

  defaultExpireDate,

  formatNow,

  getTaggedAt,

  isHighRiskLevel,

  isLegalRiskTag,

  nextId,

  nextReviewDateFromCycle,

  normalizeRiskTag,

  todayDate,

  triggersBlacklistHint,

} from '../utils/riskTagStore';



interface RiskTagApplyFormSectionProps {

  form: RiskTagApplyForm;

  currentUser: MockUser;

  onChange: (patch: Partial<RiskTagApplyForm>) => void;

  disabledTagNames?: string[];

}



export function RiskTagApplyFormSection({

  form,

  currentUser,

  onChange,

  disabledTagNames = [],

}: RiskTagApplyFormSectionProps) {

  const inputRef = useRef<HTMLInputElement>(null);



  const canAdd = canAddRiskTags(currentUser);

  const categories = selectableCategoriesForRole(currentUser);

  const isAdmin = currentUser.role === 'admin';

  const activeCategory = form.tagCategory || roleToTagCategory(currentUser);

  const isLegalForm = activeCategory === 'legal';

  const taggedAt = form.taggedAt || form.effectiveDate;



  const selectableTags = useMemo(() => {

    const pool = isAdmin

      ? (form.tagCategory ? tagsForCategory(form.tagCategory) : [])

      : tagsForCategory(activeCategory);

    return pool.filter((tag) => canApplyRiskTag(currentUser, tag));

  }, [activeCategory, currentUser, form.tagCategory, isAdmin]);



  const selectableGroups = useMemo(

    () => TAG_GROUPS.map((group) => ({

      ...group,

      tags: group.tagNames

        .map((name) => TAG_CATALOG_MAP[name])

        .filter((tag): tag is NonNullable<typeof tag> =>

          Boolean(tag && selectableTags.some((t) => t.tagCode === tag.tagCode)),

        ),

    })).filter((group) => group.tags.length > 0),

    [selectableTags],

  );



  const operationTaggedAt = taggedAt || todayDate();

  const handleCategoryChange = (category: TagCategoryCode) => {
    const taggedAtValue = todayDate();

    const catalogCycle = (TAG_CATALOG_MAP[form.tagName]?.reviewCycle ?? '3个月') as typeof form.reviewCycle;

    onChange({

      tagCategory: category,

      tagName: '',

      riskLevel: 'medium',

      taggedAt: taggedAtValue,

      effectiveDate: taggedAtValue,

      reviewCycle: category === 'legal' ? catalogCycle : form.reviewCycle,

      nextReviewAt: category === 'legal'

        ? nextReviewDateFromCycle(taggedAtValue, catalogCycle)

        : '',

      expireDate: category === 'legal' ? '' : defaultExpireDate(category, taggedAtValue),

    });

  };



  const handleTagNameChange = (tagName: string) => {

    const catalog = TAG_CATALOG_MAP[tagName];

    if (!catalog) return;

    const taggedAtValue = todayDate();

    const reviewCycle = (catalog.reviewCycle as typeof form.reviewCycle) || '3个月';

    const isLegal = catalog.tagCategory === 'legal';

    onChange({

      tagName,

      tagCategory: catalog.tagCategory,

      riskLevel: catalog.defaultLevel,

      reviewCycle,

      taggedAt: taggedAtValue,

      effectiveDate: taggedAtValue,

      nextReviewAt: isLegal ? nextReviewDateFromCycle(taggedAtValue, reviewCycle) : '',

      expireDate: isLegal ? '' : defaultExpireDate(catalog.tagCategory, taggedAtValue),

    });

  };



  const handleReviewCycleChange = (reviewCycle: typeof form.reviewCycle) => {

    const taggedAtValue = todayDate();

    onChange({

      reviewCycle,

      taggedAt: taggedAtValue,

      effectiveDate: taggedAtValue,

      nextReviewAt: nextReviewDateFromCycle(taggedAtValue, reviewCycle),

    });

  };



  const handleUpload = (file: File) => {

    const attachment: RiskTagAttachment = {

      id: nextId('att'),

      name: file.name,

      size: `${Math.max(1, Math.round(file.size / 1024))} KB`,

      uploadedAt: formatNow(),

      attachmentType: activeCategory === 'legal' ? 'legal' : activeCategory === 'finance' ? 'finance' : 'general',

    };

    onChange({ attachments: [...form.attachments, attachment] });

  };



  const removeAttachment = (id: string) => {

    onChange({ attachments: form.attachments.filter((item) => item.id !== id) });

  };



  const needsApproval = isHighRiskLevel(form.riskLevel);

  const levelLocked = Boolean(form.tagName);

  const blacklistHint = form.tagName ? triggersBlacklistHint(form.tagName) : false;



  if (!canAdd) {

    return (

      <div className="cm-risk-no-permission">

        <p>当前角色无权新增风险标签</p>

        <span className="cm-muted">当前角色仅可查看，如需打标请联系法务、财务或业管。</span>

      </div>

    );

  }



  return (

    <div className="cm-risk-form">

      <div className="cm-risk-form-grid">

        <label className="cm-form-field">

          <span className="cm-form-label">标签类型 <span className="cm-required">*</span></span>

          <select

            className={`vm-input ${!isAdmin ? 'cm-input-disabled' : ''}`}

            value={activeCategory}

            disabled={!isAdmin}

            aria-readonly={!isAdmin}

            onChange={(e) => handleCategoryChange(e.target.value as TagCategoryCode)}

          >

            {(isAdmin ? (['legal', 'finance', 'business'] as TagCategoryCode[]) : categories).map((cat) => (

              <option key={cat} value={cat}>{TAG_CATEGORY_META[cat].name}</option>

            ))}

          </select>

          {!isAdmin && (

            <span className="cm-form-hint">根据当前角色（{roleLabel(currentUser.role)}）自动带出</span>

          )}

        </label>

        <label className="cm-form-field">

          <span className="cm-form-label">标签名称 <span className="cm-required">*</span></span>

          <select

            className="vm-input"

            value={form.tagName}

            onChange={(e) => handleTagNameChange(e.target.value)}

          >

            <option value="">请选择标签</option>

            {selectableGroups.map((group) => (

              <optgroup key={group.groupName} label={group.groupName}>

                {group.tags.map((item) => (

                  <option

                    key={item.tagCode}

                    value={item.tagName}

                    disabled={disabledTagNames.includes(item.tagName)}

                  >

                    {item.tagName}

                    {disabledTagNames.includes(item.tagName) ? '（已存在）' : ''}

                  </option>

                ))}

              </optgroup>

            ))}

          </select>

          {selectableGroups.length === 0 && (

            <span className="cm-form-hint">当前角色无可选标签，请切换法务/财务/业管角色</span>

          )}

        </label>

        <label className="cm-form-field">

          <span className="cm-form-label">风险级别 <span className="cm-required">*</span></span>

          <select

            className={`vm-input ${levelLocked ? 'cm-input-disabled' : ''}`}

            value={form.riskLevel}

            disabled={levelLocked}

            aria-readonly={levelLocked}

            onChange={(e) => onChange({ riskLevel: e.target.value as RiskLevelCode })}

          >

            {(levelLocked

              ? [form.riskLevel]

              : (Object.keys(RISK_LEVEL_LABELS) as RiskLevelCode[])

            ).map((level) => (

              <option key={level} value={level}>{RISK_LEVEL_LABELS[level]}</option>

            ))}

          </select>

          {levelLocked && <span className="cm-form-hint">根据标签规范自动带出</span>}

        </label>

        <label className="cm-form-field" data-annotation-id="cm-risk-tagged-at">

          <span className="cm-form-label">打标时间 <span className="cm-required">*</span></span>

          <input

            type="date"

            className="vm-input cm-input-disabled"

            value={operationTaggedAt}

            disabled

            readOnly

            aria-readonly

          />

          <span className="cm-form-hint">根据操作当天自动确认，不可编辑</span>

        </label>

        {isLegalForm ? (

          <>

            <label className="cm-form-field">

              <span className="cm-form-label">复核周期 <span className="cm-required">*</span></span>

              <select

                className="vm-input"

                value={form.reviewCycle}

                onChange={(e) => handleReviewCycleChange(e.target.value as typeof form.reviewCycle)}

              >

                {REVIEW_CYCLE_OPTIONS.map((option) => (

                  <option key={option} value={option}>{option}</option>

                ))}

              </select>

            </label>

            <label className="cm-form-field" data-annotation-id="cm-risk-next-review-at">

              <span className="cm-form-label">下次复核时间 <span className="cm-required">*</span></span>

              <input

                type="date"

                className="vm-input cm-input-disabled"

                value={form.nextReviewAt}

                disabled

                readOnly

                aria-readonly

              />

              <span className="cm-form-hint">根据复核周期自动推算，不可编辑；到期仅提醒责任人复核，不会自动解除标签。</span>

            </label>

          </>

        ) : (

          <>

            <span className="cm-risk-form-grid-spacer" aria-hidden />

            <label className="cm-form-field">

            <span className="cm-form-label">有效期至 <span className="cm-required">*</span></span>

            <input

              type="date"

              className="vm-input"

              value={form.expireDate}

              onChange={(e) => onChange({ expireDate: e.target.value })}

            />

            <span className="cm-form-hint">财务/业管标签的业务有效期，与复核提醒无关。</span>

          </label>

          </>

        )}

      </div>



      <label className="cm-form-field cm-risk-form-full">

        <span className="cm-form-label">原因说明 <span className="cm-required">*</span></span>

        <textarea

          className="vm-input cm-textarea"

          rows={3}

          value={form.reason}

          placeholder="请说明打标依据，供审批留痕（至少 10 字）"

          onChange={(e) => onChange({ reason: e.target.value })}

        />

      </label>



      <div className="cm-form-field cm-risk-form-full">

        <span className="cm-form-label">

          附件上传 {needsApproval && <span className="cm-required">*</span>}

        </span>

        <button

          type="button"

          className="vm-upload-zone cm-risk-upload"

          onClick={() => inputRef.current?.click()}

        >

          <Upload size={20} aria-hidden />

          <p>上传审批依据、合同、对账单等</p>

          <p className="hint">支持 .pdf、.jpg、.png、.xlsx</p>

          <input

            ref={inputRef}

            type="file"

            accept=".pdf,.jpg,.jpeg,.png,.xlsx,.xls"

            className="sr-only"

            onChange={(e) => {

              const file = e.target.files?.[0];

              if (file) handleUpload(file);

              e.target.value = '';

            }}

          />

        </button>

        {form.attachments.length > 0 && (

          <ul className="cm-risk-attachments">

            {form.attachments.map((file) => (

              <li key={file.id}>

                <span>{file.name}</span>

                <span className="cm-muted">{file.size}</span>

                <button type="button" className="vm-btn vm-btn-link" onClick={() => removeAttachment(file.id)}>

                  移除

                </button>

              </li>

            ))}

          </ul>

        )}

      </div>



      {needsApproval && (

        <div className="cm-risk-alert">

          高风险/致命标签提交后将进入<strong>待审批</strong>状态，需法务/风控/管理层确认后生效。

        </div>

      )}

      {blacklistHint && (

        <div className="cm-risk-alert cm-risk-alert--warn">

          该标签可能触发<strong>黑名单审批</strong>，提交后将进入联合复核流程。

        </div>

      )}

    </div>

  );

}



interface RiskTagReviewFormSectionProps {

  form: RiskTagReviewForm;

  onChange: (patch: Partial<RiskTagReviewForm>) => void;

}



export function RiskTagReviewFormSection({ form, onChange }: RiskTagReviewFormSectionProps) {

  const inputRef = useRef<HTMLInputElement>(null);

  const needsNextReview = form.conclusion !== 'riskResolved';

  const needsRemoveReason = form.conclusion === 'riskResolved';



  const handleUpload = (file: File) => {

    const attachment: RiskTagAttachment = {

      id: nextId('att'),

      name: file.name,

      size: `${Math.max(1, Math.round(file.size / 1024))} KB`,

      uploadedAt: formatNow(),

      attachmentType: 'legal',

    };

    onChange({ attachments: [...form.attachments, attachment] });

  };



  return (

    <div className="cm-risk-review-form">

      <label className="cm-form-field cm-risk-form-full">

        <span className="cm-form-label">复核结论 <span className="cm-required">*</span></span>

        <select

          className="vm-input"

          value={form.conclusion}

          onChange={(e) => onChange({

            conclusion: e.target.value as RiskTagReviewForm['conclusion'],

            removeReason: '',

            nextReviewAt: e.target.value === 'riskResolved' ? '' : form.nextReviewAt,

          })}

        >

          {(Object.keys(REVIEW_CONCLUSION_LABELS) as RiskTagReviewForm['conclusion'][]).map((key) => (

            <option key={key} value={key}>{REVIEW_CONCLUSION_LABELS[key]}</option>

          ))}

        </select>

      </label>

      <label className="cm-form-field cm-risk-form-full">

        <span className="cm-form-label">复核说明 <span className="cm-required">*</span></span>

        <textarea

          className="vm-input cm-textarea"

          rows={3}

          value={form.note}

          placeholder="请说明本次复核依据与结论（至少 5 字）"

          onChange={(e) => onChange({ note: e.target.value })}

        />

      </label>

      {needsNextReview && (

        <label className="cm-form-field cm-risk-form-full">

          <span className="cm-form-label">下次复核时间 <span className="cm-required">*</span></span>

          <input

            type="date"

            className="vm-input"

            value={form.nextReviewAt}

            onChange={(e) => onChange({ nextReviewAt: e.target.value })}

          />

          <span className="cm-form-hint">到期仅提醒责任人复核，不会自动解除标签。</span>

        </label>

      )}

      {needsRemoveReason && (

        <label className="cm-form-field cm-risk-form-full">

          <span className="cm-form-label">解除原因 <span className="cm-required">*</span></span>

          <textarea

            className="vm-input cm-textarea"

            rows={2}

            value={form.removeReason}

            placeholder="确认风险已解除，请填写解除原因（至少 5 字）"

            onChange={(e) => onChange({ removeReason: e.target.value })}

          />

        </label>

      )}

      <div className="cm-form-field cm-risk-form-full">

        <span className="cm-form-label">附件（可选）</span>

        <button

          type="button"

          className="vm-upload-zone cm-risk-upload"

          onClick={() => inputRef.current?.click()}

        >

          <Upload size={20} aria-hidden />

          <p>上传复核材料</p>

          <input

            ref={inputRef}

            type="file"

            accept=".pdf,.jpg,.jpeg,.png,.xlsx,.xls"

            className="sr-only"

            onChange={(e) => {

              const file = e.target.files?.[0];

              if (file) handleUpload(file);

              e.target.value = '';

            }}

          />

        </button>

        {form.attachments.length > 0 && (

          <ul className="cm-risk-attachments">

            {form.attachments.map((file) => (

              <li key={file.id}>{file.name}（{file.size}）</li>

            ))}

          </ul>

        )}

      </div>

    </div>

  );

}



interface RiskTagDetailCardProps {

  tag: import('../types/riskTag').CustomerRiskTag;

  currentUser: MockUser;

  onClose?: () => void;

}



export function RiskTagDetailCard({ tag, currentUser, onClose }: RiskTagDetailCardProps) {

  const normalized = normalizeRiskTag(tag);

  const isLegal = isLegalRiskTag(normalized);

  const showFinance = normalized.sensitiveLevel === 'financeSensitive';

  const showLegalAttachments = normalized.sensitiveLevel === 'legalSensitive';

  const canFinance = ['finance', 'manager', 'admin'].includes(currentUser.role);

  const canLegal = ['legal', 'riskControl', 'manager', 'admin'].includes(currentUser.role);



  return (

    <div className="cm-risk-detail-card">

      <div className="cm-risk-detail-head">

        <div>

          <h4>{normalized.tagName}</h4>

          <span className={`cm-risk-status cm-risk-status--${normalized.status}`}>

            {normalized.reviewStatus === 'overdue' && isLegal ? '待复核' : normalized.statusName}

          </span>

        </div>

        {onClose && (

          <button type="button" className="vm-modal-close" onClick={onClose} aria-label="关闭详情">

            <X size={16} aria-hidden />

          </button>

        )}

      </div>

      <dl className="cm-risk-detail-list">

        <div><dt>标签类型</dt><dd>{normalized.tagCategoryName}</dd></div>

        <div><dt>风险级别</dt><dd>{normalized.riskLevelName}</dd></div>

        <div><dt>责任部门</dt><dd>{normalized.responsibleDept}</dd></div>

        <div><dt>打标时间</dt><dd>{getTaggedAt(normalized)}</dd></div>

        {isLegal ? (

          <>

            <div><dt>复核周期</dt><dd>{normalized.reviewCycle}</dd></div>

            <div><dt>下次复核时间</dt><dd>{normalized.nextReviewAt || '—'}</dd></div>

            <div><dt>最后复核时间</dt><dd>{normalized.lastReviewedAt || '—'}</dd></div>

          </>

        ) : (

          <div><dt>有效期至</dt><dd>{normalized.expireDate}</dd></div>

        )}

        <div><dt>来源</dt><dd>{normalized.sourceName}</dd></div>

        <div><dt>操作人</dt><dd>{normalized.createdBy}</dd></div>

        <div><dt>提交时间</dt><dd>{normalized.createdAt}</dd></div>

        {normalized.approvedBy && <div><dt>审批人</dt><dd>{normalized.approvedBy}</dd></div>}

        {normalized.approvedAt && <div><dt>审批时间</dt><dd>{normalized.approvedAt}</dd></div>}

        {normalized.removedAt && <div><dt>解除时间</dt><dd>{normalized.removedAt}</dd></div>}

        {normalized.removeReason && <div className="cm-risk-detail-full"><dt>解除原因</dt><dd>{normalized.removeReason}</dd></div>}

        {normalized.rejectReason && <div className="cm-risk-detail-full"><dt>驳回原因</dt><dd>{normalized.rejectReason}</dd></div>}

        <div className="cm-risk-detail-full"><dt>原因说明</dt><dd>{normalized.reason}</dd></div>



        {showFinance && (

          <div className="cm-risk-detail-full">

            <dt>财务明细</dt>

            <dd>

              {canFinance && normalized.financeDetail ? (

                <ul className="cm-risk-sensitive-list">

                  {normalized.financeDetail.overdueAmount && <li>逾期金额：{normalized.financeDetail.overdueAmount}</li>}

                  {normalized.financeDetail.billNo && <li>账单编号：{normalized.financeDetail.billNo}</li>}

                  {normalized.financeDetail.receivableNote && <li>{normalized.financeDetail.receivableNote}</li>}

                </ul>

              ) : (

                <span className="cm-sensitive-hint">财务敏感信息已隐藏</span>

              )}

            </dd>

          </div>

        )}



        {normalized.attachments.length > 0 && (

          <div className="cm-risk-detail-full">

            <dt>附件</dt>

            <dd>

              {showLegalAttachments && !canLegal ? (

                <span className="cm-sensitive-hint">法务敏感附件仅授权角色可见</span>

              ) : (

                <ul className="cm-risk-attachments">

                  {normalized.attachments.map((file) => (

                    <li key={file.id}>{file.name}（{file.size}）</li>

                  ))}

                </ul>

              )}

            </dd>

          </div>

        )}



        {isLegal && (normalized.reviewLogs?.length ?? 0) > 0 && (

          <div className="cm-risk-detail-full">

            <dt>复核记录</dt>

            <dd>

              <ul className="cm-risk-review-log-list">

                {normalized.reviewLogs!.map((log) => (

                  <li key={log.id}>

                    <strong>{log.conclusionName}</strong>

                    <span className="cm-muted"> · {log.reviewedAt} · {log.reviewedBy}</span>

                    <p>{log.note}</p>

                  </li>

                ))}

              </ul>

            </dd>

          </div>

        )}

      </dl>

    </div>

  );

}

