/* global React, Icon, Button, Field, Select, NumInput, RadioCard, SegControl, PortalSelect,
   useToast, PageHead, InfoNote, StatusSwitch,
   APPROVAL_FORMS, COND_TYPES, COMBINATORS, STEP_TYPES,
   POSITIONS, USERS, AF_FIELDS, POSITION_USER_MAP,
   WATCH_FIELDS, WATCH_FIELDS_ALL,
   OPERATORS_BY_TYPE, getOperators, getOperator, getFieldType */
// 審核流程設定 — L2 新增 / 編輯

const { useState, useMemo, useEffect, useRef } = React;

const blankStep = () => ({ type: "role", values: [] });
const blankRule = () => ({ field: "", op: "lte", value: "", value2: "" });

const newFlowDraft = () => ({
  id: null,
  name: "",
  formId: "",
  department: "all",
  condType: "field",
  combinator: "and",
  steps: [blankStep()],
  rules: [blankRule()],
  enabled: true,
});


/* ============ Rule value cell — switches by operator shape ============ */
const RuleValue = ({ rule, onChange, error }) => {
  const meta = AF_FIELDS[rule.field] || { type: "text" };
  const op = getOperator(rule.field, rule.op);
  const shape = op.valueShape;

  if (shape === "none") {
    return <Field value="" placeholder="（不需填值）" disabled />;
  }
  // shape === 'one'
  if (meta.type === "percent") {
    return <NumInput value={rule.value} onChange={e => onChange({ value: e.target.value })} unit="%" placeholder="請輸入" error={error} />;
  }
  if (meta.type === "number") {
    return <NumInput value={rule.value} onChange={e => onChange({ value: e.target.value })} unit={meta.unit} placeholder="請輸入" error={error} />;
  }
  if (meta.type === "enum") {
    return (
      <PortalSelect
        value={rule.value || ""}
        onChange={(v) => onChange({ value: v })}
        options={(meta.options || []).map(o => ({ value: o, label: o }))}
        placeholder="請選擇"
        triggerClassName={"field-trigger" + (error ? " field-trigger--error" : "")}
        triggerStyle={{ width: "100%" }}
      />
    );
  }
  return <Field value={rule.value || ""} onChange={e => onChange({ value: e.target.value })} placeholder="請輸入" error={error} />;
};

/* ============ Main form ============ */
const ApprovalForm = ({ initial, onCancel, onSave, onDirtyChange }) => {
  const isEdit = !!(initial && initial.id);
  const [draft, setDraft] = useState(() => initial
    ? { ...initial, steps: initial.steps.map(s => ({ ...s, values: [...(s.values || [])] })), rules: initial.rules.map(r => ({ ...r })) }
    : newFlowDraft());
  const [touched, setTouched] = useState({});
  const [dirty, setDirty] = React.useState(false);
  const toast = useToast();

  // Dirty tracking
  useEffect(() => {
    if (!onDirtyChange) return;
    const baseline = initial ? JSON.stringify(initial) : JSON.stringify(newFlowDraft());
    const isDirty = JSON.stringify(draft) !== baseline;
    setDirty(isDirty);
    onDirtyChange?.(isDirty);
  }, [draft, initial, onDirtyChange]);

  // Cleanup dirty on unmount
  useEffect(() => () => { if (onDirtyChange) onDirtyChange(false); }, [onDirtyChange]);

  const set = (k, v) => setDraft(d => ({ ...d, [k]: v }));

  // ----- Steps -----
  const setStep = (i, patch) => setDraft(d => ({
    ...d,
    steps: d.steps.map((s, idx) => idx === i ? { ...s, ...patch } : s),
  }));
  const setStepType = (i, type) => setStep(i, { type, values: [] });
  const setStepValues = (i, values) => setStep(i, { values });
  const addStep = () => setDraft(d => ({ ...d, steps: [...d.steps, blankStep()] }));
  const delStep = (i) => setDraft(d => ({ ...d, steps: d.steps.filter((_, idx) => idx !== i) }));

  // ----- Rules -----
  const setRule = (i, patch) => setDraft(d => ({
    ...d,
    rules: d.rules.map((r, idx) => idx === i ? { ...r, ...patch } : r),
  }));
  const setRuleField = (i, field) => {
    const ops = getOperators(field);
    setDraft(d => ({
      ...d,
      rules: d.rules.map((r, idx) => idx === i ? { ...r, field, op: ops[0]?.id || "is", value: "", value2: "" } : r),
    }));
  };
  const setRuleOp = (i, op) => {
    setDraft(d => ({
      ...d,
      rules: d.rules.map((r, idx) => {
        if (idx !== i) return r;
        const prevShape = getOperator(r.field, r.op).valueShape;
        const nextShape = getOperator(r.field, op).valueShape;
        const reset = prevShape !== nextShape;
        return { ...r, op, ...(reset ? { value: nextShape === "multi" ? [] : "", value2: "" } : {}) };
      }),
    }));
  };
  const addRule = () => setDraft(d => ({ ...d, rules: [...d.rules, blankRule()] }));
  const delRule = (i) => setDraft(d => ({ ...d, rules: d.rules.filter((_, idx) => idx !== i) }));

  // Watch fields scoped to form
  const watchFields = useMemo(() => {
    const list = WATCH_FIELDS[draft.formId] || [];
    return list.length === 0 ? WATCH_FIELDS_ALL : list;
  }, [draft.formId]);

  // Prune rules when form changes
  useEffect(() => {
    setDraft(d => {
      const valid = new Set(WATCH_FIELDS[d.formId] || WATCH_FIELDS_ALL);
      const rules = d.rules.map(r => valid.has(r.field) ? r : { ...r, field: "", op: "lte", value: "", value2: "" });
      return { ...d, rules };
    });
    // eslint-disable-next-line
  }, [draft.formId]);

  // ----- Auto-name suggestion -----
  const suggestedName = useMemo(() => {
    if (!draft.formId) return "";
    const form = APPROVAL_FORMS.find(f => f.id === draft.formId);
    const first = draft.steps[0];
    const approver = first?.values?.[0];
    if (!form) return "";
    if (!approver) return `${form.label} 審核`;
    return `${form.label} · ${approver} 審核`;
  }, [draft.formId, draft.steps]);

  // ----- Validation -----
  const errors = useMemo(() => {
    const e = {};
    if (!draft.name.trim()) e.name = "請填寫名稱";
    if (!draft.formId) e.formId = "請選擇作用表單";
    draft.steps.forEach((s, i) => {
      if (!s.values || s.values.length === 0) e["step_" + i] = "請至少選 1 位審核人";
    });
    if (draft.steps.length === 0) e.steps = "至少需要 1 個審核步驟";
    // Check step approver overlap across steps
    const resolvedSets = draft.steps.map(s => {
      if (s.type === "role") return new Set(POSITION_USER_MAP[s.values?.[0]] || []);
      return new Set(s.values?.[0] ? [s.values[0]] : []);
    });
    const overlapMsgs = [];
    draft.steps.forEach((_, i) => {
      for (let j = i + 1; j < draft.steps.length; j++) {
        const overlap = [...resolvedSets[i]].filter(u => resolvedSets[j].has(u));
        if (overlap.length > 0) {
          overlapMsgs.push(`步驟 ${i + 1} 與步驟 ${j + 1} 審核人員重疊（${overlap.join("、")}），請調整`);
        }
      }
    });
    if (overlapMsgs.length > 0) e.steps_overlap = overlapMsgs.join("；");
    if (draft.condType === "field") {
      const nonEmpty = draft.rules.filter(r => r.field);
      if (nonEmpty.length === 0) e.rules = "請至少設定 1 條欄位規則";
      draft.rules.forEach((r, i) => {
        if (!r.field) return;
        const shape = getOperator(r.field, r.op).valueShape;
        if (shape === "one" && !String(r.value ?? "").trim()) e["rule_" + i] = "請填寫值";
      });
    }
    return e;
  }, [draft]);

  const hasErrors = Object.keys(errors).length > 0;

  const submit = () => {
    setTouched(Object.fromEntries(Object.keys(errors).map(k => [k, true])));
    if (hasErrors) {
      toast.push({ msg: "尚有欄位未填寫完整", kind: "warning" });
      return;
    }
    const form = APPROVAL_FORMS.find(f => f.id === draft.formId);
    const cleanRules = draft.condType === "field" ? draft.rules.filter(r => r.field) : [];
    toast.push({ msg: isEdit ? "審核流程已更新" : "審核流程已建立", kind: "success" });
    onSave({ ...draft, formLabel: form ? form.label : "", rules: cleanRules }, isEdit);
  };

  const showErr = (k) => touched[k] && errors[k];

  // Group APPROVAL_FORMS for optgroup
  const formGroups = useMemo(() => {
    const g = {};
    APPROVAL_FORMS.forEach(f => { (g[f.group] ||= []).push(f); });
    return g;
  }, []);

  return (
    <>
      <PageHead
        crumbs={[
          { label: "帳號與權限" },
          { label: "審核流程設定", onClick: onCancel },
          { label: isEdit ? "編輯" : "新增", current: true },
        ]}
        title={isEdit ? "編輯審核流程" : "新增審核流程"}
        dirty={dirty}
        actions={<>
          <Button variant="default" onClick={onCancel}>取消</Button>
          <Button variant="primary" onClick={submit}>{isEdit ? "儲存變更" : "建立流程"}</Button>
        </>}
      />

      <div className="card af-form">
        <div className="card__body">

          {/* 名稱 */}
          <div className="form-row">
            <span className="lab req">名稱</span>
            <div>
              <Field
                value={draft.name}
                onChange={e => set("name", e.target.value)}
                placeholder={suggestedName || "例：低毛利覆核、二階主管覆核"}
                error={!!showErr("name")}
                style={{ maxWidth: 296 }}
              />
              {showErr("name") && <div className="help err">{errors.name}</div>}
              {!draft.name && suggestedName && (
                <div className="help" style={{ marginTop: 4 }}>
                  建議命名：<a onClick={() => set("name", suggestedName)} style={{ cursor: "pointer" }}>{suggestedName}</a>
                </div>
              )}
            </div>
          </div>

          {/* 作用表單 */}
          <div className="form-row">
            <span className="lab req">作用表單</span>
            <div>
              <PortalSelect
                value={draft.formId}
                onChange={(v) => set("formId", v)}
                options={Object.entries(formGroups).map(([g, fs]) => ({
                  group: g,
                  options: fs.map(f => ({ value: f.id, label: f.label })),
                }))}
                placeholder="請選擇"
                triggerClassName={"field-trigger" + (showErr("formId") ? " field-trigger--error" : "")}
                triggerStyle={{ maxWidth: 296 }}
              />
              {showErr("formId") && <div className="help err">{errors.formId}</div>}
            </div>
          </div>

          {/* 條件類型 */}
          <div className="form-row">
            <span className="lab req">觸發時機</span>
            <div>
              <RadioCard
                options={COND_TYPES}
                value={draft.condType}
                onChange={(id) => set("condType", id)}
                name="condType"
              />
            </div>
          </div>

          {/* 規則設定 — only when 依欄位規則 */}
          {draft.condType === "field" && (
            <div className="form-row">
              <span className="lab req">欄位規則</span>
              <div>
                {/* Combinator segmented control */}
                <SegControl
                  options={COMBINATORS}
                  value={draft.combinator}
                  onChange={(id) => set("combinator", id)}
                />

                <div className="af-rules-grid">
                  <div className="af-rules-grid__head">
                    <div>監看欄位</div>
                    <div>條件式</div>
                    <div>值</div>
                    <div></div>
                  </div>
                  {draft.rules.map((r, i) => {
                    const ops = r.field ? getOperators(r.field) : [];
                    return (
                      <div key={i} className="af-rules-grid__row">
                        <PortalSelect
                          value={r.field}
                          onChange={(v) => setRuleField(i, v)}
                          options={watchFields.map(f => ({ value: f, label: f }))}
                          placeholder={draft.formId ? "請選擇" : "請先選作用表單"}
                          triggerClassName="field-trigger"
                          triggerStyle={{ width: "100%" }}
                          disabled={!draft.formId}
                        />
                        <PortalSelect
                          value={r.field ? r.op : ""}
                          onChange={(v) => setRuleOp(i, v)}
                          options={ops.map(o => ({ value: o.id, label: o.label }))}
                          placeholder="依欄位型態決定"
                          triggerClassName="field-trigger"
                          triggerStyle={{ width: "100%" }}
                          disabled={!r.field}
                        />
                        <div>
                          <RuleValue rule={r} onChange={(patch) => setRule(i, patch)} error={!!showErr("rule_" + i)} />
                          {showErr("rule_" + i) && <div className="help err" style={{ marginTop: 2 }}>{errors["rule_" + i]}</div>}
                        </div>
                        <button
                          className="af-icon-btn"
                          title={draft.rules.length === 1 ? "至少保留 1 條" : "刪除此規則"}
                          disabled={draft.rules.length === 1}
                          onClick={() => delRule(i)}
                        >
                          <Icon name="trash" size={16} />
                        </button>
                      </div>
                    );
                  })}
                  <div className="af-rules-grid__foot">
                    <Button variant="default" size="sm" icon="plus" onClick={addRule}>新增一條</Button>
                    <span className="af-rules-grid__hint">
                      多條規則之間採 <b>{draft.combinator === "and" ? "全部成立 (AND)" : "任一成立 (OR)"}</b>。
                    </span>
                  </div>
                </div>
                {showErr("rules") && <div className="help err" style={{ marginTop: 6 }}>{errors.rules}</div>}
              </div>
            </div>
          )}

          {/* 審核流程步驟 */}
          <div className="form-row">
            <span className="lab req">審核流程步驟</span>
            <div>
              <div className="af-steps">
                {draft.steps.map((s, i) => {
                  const opts = s.type === "role" ? POSITIONS : USERS;
                  return (
                    <div key={i} className="af-steps__entry">
                      <div className="af-steps__row">
                        <div className="af-steps__num">Step {i + 1}</div>
                        <div className="af-steps__field">
                          <label className="af-steps__lbl">類型</label>
                          <PortalSelect
                            value={s.type}
                            onChange={(v) => setStepType(i, v)}
                            options={STEP_TYPES.map(t => ({ value: t.id, label: t.label }))}
                            placeholder="—"
                            triggerClassName="field-trigger"
                            triggerStyle={{ width: 100 }}
                          />
                        </div>
                        <div className="af-steps__field af-steps__field--approvers">
                          <label className="af-steps__lbl">
                            {s.type === "role" ? "指定職位" : "指定人員"}
                          </label>
                          <PortalSelect
                            value={s.values?.[0] || ""}
                            onChange={(v) => setStepValues(i, v ? [v] : [])}
                            options={opts}
                            placeholder="請選擇（單選）"
                            triggerClassName={"field-trigger" + (showErr("step_" + i) ? " field-trigger--error" : "")}
                            triggerStyle={{ width: "100%" }}
                          />
                        </div>
                        <button
                          className="af-icon-btn"
                          title={draft.steps.length === 1 ? "至少需要 1 個步驟" : "刪除此步驟"}
                          disabled={draft.steps.length === 1}
                          onClick={() => delStep(i)}
                        >
                          <Icon name="trash" size={16} />
                        </button>
                      </div>
                      {showErr("step_" + i) && <div className="help err af-steps__errmsg">{errors["step_" + i]}</div>}
                    </div>
                  );
                })}
              </div>
              <Button variant="default" size="sm" icon="plus" onClick={addStep} style={{ marginTop: 8 }}>新增審核步驟</Button>
              {showErr("steps_overlap") && <div className="help err" style={{ marginTop: 6 }}>{errors.steps_overlap}</div>}
              <div className="af-steps__hint">
                依序由 Step 1 → Step n 逐關簽核；任一關退回，整張表單退回申請人重編。每關指定一位人員或一種職位。
              </div>
            </div>
          </div>

          {/* 啟用狀態 — toggle */}
          <div className="form-row">
            <span className="lab req">狀態</span>
            <div>
              <StatusSwitch on={draft.enabled} onClick={() => set("enabled", !draft.enabled)} />
              <div className="help" style={{ marginTop: 6 }}>
                停用後，新送出的表單將略過此審核流程；目前進行中的審核單會繼續走完此流程。
              </div>
            </div>
          </div>

        </div>

      </div>
    </>
  );
};

Object.assign(window, { ApprovalForm, newFlowDraft });
