'use client';

import {
  useActionState,
  useEffect,
  useRef,
  useState,
  useTransition,
} from 'react';
import { FoxButton } from '@fox/core/components/fox-button';
import { FoxFormLabel } from '@fox/core/components/fox-form-label';
import { FoxHelperText } from '@fox/core/components/fox-helper-text';
import { FoxInput } from '@fox/core/components/fox-input';
import { FoxModal } from '@fox/core/components/fox-modal';
import { FoxRadio } from '@fox/core/components/fox-radio';
import { FoxRadioGroup } from '@fox/core/components/fox-radio-group';
import { FoxSelect } from '@fox/core/components/fox-select';
import { submitFormAction } from '@/app/_hooks/submit-form-action';
import { useFeedback } from '@/app/_hooks/use-feedback';
import {
  DEFAULT_MERCHANT_DIVISION_CODE,
  formatOptionalValue,
  type Merchant,
  type MerchantCodeTables,
} from '@/lib/domain/merchant';
import {
  ADDRESS_DETAIL_MAX_LENGTH,
  INITIAL_MERCHANT_FORM_STATE,
  MEMO_MAX_LENGTH,
  NAME_MAX_LENGTH,
  ACCOUNT_NUMBER_MAX_LENGTH,
  OWNER_MAX_LENGTH,
} from '@/lib/domain/merchant-form';
import { saveMerchantAction } from '../_actions';
import { openPostcodeSearch } from '@/app/_components/postcode';
import styles from './merchant-form.module.scss';

interface MerchantFormModalProps {
  merchant?: Merchant;
  /** 업종·업태·구분·은행 코드표 — 선택지. */
  codeTables: MerchantCodeTables;
  onClose: () => void;
}

/**
 * 가맹몰(가맹점) 등록·수정 모달 — 기획 MCH_002_p·MCH_003_p. 모든 항목을 고칠 수 있다(사용자 확정).
 * 요청은 백엔드 `MngrVocInsertReqVo`/`MngrVocUpdateReqVo`대로 보낸다 — 지금은 BizPlay(웹캐시)로
 * 위임되고 곧 우리 DB 저장으로 바뀐다.
 */
export function MerchantFormModal({ merchant, codeTables, onClose }: MerchantFormModalProps) {
  const isEdit = Boolean(merchant);
  const { showToast } = useFeedback();
  const formRef = useRef<HTMLFormElement>(null);
  const [state, formAction, isPending] = useActionState(
    saveMerchantAction,
    INITIAL_MERCHANT_FORM_STATE
  );

  const [categoryCode, setCategoryCode] = useState(merchant?.categoryCode ?? '');
  const [businessStatusCode, setBusinessStatusCode] = useState(merchant?.businessStatusCode ?? '');
  const [divisionCode, setDivisionCode] = useState(
    merchant?.divisionCode || DEFAULT_MERCHANT_DIVISION_CODE
  );
  const [bankCode, setBankCode] = useState('');
  // 조회 응답에 useYn이 없어 기존 가맹점은 값을 모른다 — 그때는 어느 쪽도 고르지 않는다.
  // 신규 등록만 「노출」로 시작한다.
  const [isVisible, setIsVisible] = useState<boolean | null>(
    merchant === undefined ? true : merchant.isVisible
  );
  // 주소·우편번호는 검색으로 채우거나 직접 고친다. 좌표는 검색 결과만 채운다.
  const [address, setAddress] = useState(merchant?.address ?? '');
  const [postalCode, setPostalCode] = useState(merchant?.postalCode ?? '');
  const [latitude, setLatitude] = useState(merchant?.latitude ?? '');
  const [longitude, setLongitude] = useState(merchant?.longitude ?? '');
  const [isSearching, startSearching] = useTransition();

  useEffect(() => {
    if (state.status === 'success') {
      showToast({
        variant: 'success',
        message: isEdit ? '가맹점을 수정했습니다.' : '가맹점을 등록했습니다.',
      });
      onClose();
      return;
    }

    // 칸별 오류는 해당 입력칸에 그대로 두고, 폼 전체에 걸린 사유만 토스트로 알린다 —
    // 긴 폼이라 맨 아래 문구는 스크롤 밖에 있으면 보이지 않는다.
    if (state.status === 'error' && state.message) {
      showToast({ variant: 'danger', message: state.message });
    }
  }, [state, showToast, onClose, isEdit]);

  const errors = state.status === 'error' ? (state.errors ?? {}) : {};

  /** 기획 ③ 주소 검색 연동 — 고른 주소로 우편번호·좌표까지 채운다. */
  function searchAddress() {
    startSearching(async () => {
      let picked;
      try {
        picked = await openPostcodeSearch();
      } catch {
        showToast({
          variant: 'danger',
          message: '주소 검색을 불러오지 못했습니다. 잠시 후 다시 시도해 주세요.',
        });
        return;
      }

      if (!picked) {
        return;
      }

      setAddress(picked.address);
      setPostalCode(picked.zonecode);
      setLatitude(picked.latitude);
      setLongitude(picked.longitude);
    });
  }

  return (
    <FoxModal
      dismissible={false}
      open
      size="md"
      title={isEdit ? '가맹몰 수정' : '가맹몰 등록'}
      onClose={onClose}
      actions={
        <>
          <FoxButton type="default" size="md" label="취소" onAction={onClose} />
          <FoxButton
            type="primary"
            size="md"
            label={isPending ? '저장 중...' : isEdit ? '수정' : '등록'}
            disabled={isPending}
            onAction={() => formRef.current?.requestSubmit()}
          />
        </>
      }
    >
      <form
        ref={formRef}
        onSubmit={(event) => submitFormAction(event, formAction)}
        className={styles.fields}
      >
        <input type="hidden" name="id" value={merchant?.id ?? ''} />
        <input type="hidden" name="categoryCode" value={categoryCode} />
        <input type="hidden" name="businessStatusCode" value={businessStatusCode} />
        <input type="hidden" name="divisionCode" value={divisionCode} />
        <input type="hidden" name="bankCode" value={bankCode} />
        <input type="hidden" name="isVisible" value={isVisible ? 'Y' : 'N'} />
        <input type="hidden" name="latitude" value={latitude} />
        <input type="hidden" name="longitude" value={longitude} />

        {/* 등록 시에는 코드가 아직 없다 — 저장할 때 서버가 만든다. */}
        {isEdit && (
          <div className={styles.field}>
            <FoxInput
              size="md"
              label="가맹점코드"
              value={merchant?.code ?? ''}
              readOnly
              state="view"
            />
          </div>
        )}

        {/* 메모·등록일은 백엔드에 컬럼이 없어 저장되지 않는다. 기획 시안에 있는 항목이라 화면에서는
            지우지 않고, 값이 없으면 `-`로 보여준다(사용자 확정). 브랜드명은 폼에서 뺐다(사용자 요청). */}
        <div className={styles.field}>
          <FoxInput
            size="md"
            name="name"
            label="가맹점명"
            requirement="required"
            defaultValue={merchant?.name ?? ''}
            placeholder="가맹점명을 입력하세요."
            maxLength={NAME_MAX_LENGTH}
            invalid={Boolean(errors.name)}
            message={errors.name}
          />
        </div>

        <div className={styles.field}>
          <div className={styles.pair}>
            <FoxSelect
              size="md"
              label="업종"
              requirement="required"
              options={codeTables.business.map((code) => ({ value: code.code, label: code.label }))}
              value={categoryCode}
              onValueChange={setCategoryCode}
              placeholder="선택"
              error={Boolean(errors.categoryCode)}
              hint={errors.categoryCode}
            />
            <FoxSelect
              size="md"
              label="업태"
              options={codeTables.businessStatus.map((code) => ({ value: code.code, label: code.label }))}
              value={businessStatusCode}
              onValueChange={setBusinessStatusCode}
              placeholder="선택"
            />
          </div>
        </div>

        <div className={styles.field}>
          <FoxSelect
            size="md"
            label="가맹점 구분"
            options={codeTables.division.map((code) => ({ value: code.code, label: code.label }))}
            value={divisionCode}
            onValueChange={setDivisionCode}
            placeholder="선택"
          />
        </div>

        <div className={styles.field}>
          <div className={styles.pair}>
            <FoxInput
                size="md"
              name="businessNumber"
              label="사업자등록번호"
              defaultValue={merchant?.businessNumber ?? ''}
              placeholder="000-00-00000"
              invalid={Boolean(errors.businessNumber)}
              message={errors.businessNumber}
            />
            <FoxInput
                size="md"
              name="ownerName"
              label="대표자명"
              defaultValue={merchant?.ownerName ?? ''}
              placeholder="대표자명을 입력하세요."
              maxLength={OWNER_MAX_LENGTH}
            />
          </div>
        </div>

        <div className={styles.field}>
          <FoxInput
            size="md"
            name="phoneNumber"
            label="전화번호"
            requirement="required"
            defaultValue={merchant?.phoneNumber ?? ''}
            placeholder="가게 전화번호를 입력하세요."
            invalid={Boolean(errors.phoneNumber)}
            message={errors.phoneNumber}
          />
        </div>

        <div className={styles.field}>
          <FoxFormLabel as="span" requirement="required">
            주소
          </FoxFormLabel>
          <div className={styles.addressRow}>
            <FoxInput
              size="md"
              name="postalCode"
              aria-label="우편번호"
              value={postalCode}
              onChange={setPostalCode}
              placeholder="우편번호"
              invalid={Boolean(errors.postalCode)}
              message={errors.postalCode}
            />
            <FoxButton
              type="secondary"
              size="md"
              label={isSearching ? '검색 중...' : '주소 검색'}
              disabled={isSearching}
              onAction={searchAddress}
            />
          </div>
          <FoxInput
            size="md"
            name="address"
            aria-label="주소"
            value={address}
            onChange={setAddress}
            placeholder="주소 검색으로 채우거나 직접 입력하세요."
          />
          <FoxInput
            size="md"
            name="addressDetail"
            aria-label="상세주소"
            defaultValue={merchant?.addressDetail ?? ''}
            placeholder="상세주소를 입력하세요."
            maxLength={ADDRESS_DETAIL_MAX_LENGTH}
          />
          {errors.address && (
            <FoxHelperText type="danger" message={errors.address} />
          )}
        </div>

        <div className={styles.field}>
          <FoxFormLabel as="span">위도 / 경도</FoxFormLabel>
          <div className={styles.pair}>
            <FoxInput
              size="md"
              aria-label="위도"
              value={latitude}
              readOnly
              state="view"
              placeholder="주소 검색 시 자동 입력"
            />
            <FoxInput
              size="md"
              aria-label="경도"
              value={longitude}
              readOnly
              state="view"
              placeholder="주소 검색 시 자동 입력"
            />
          </div>
        </div>

        <div className={styles.field}>
          <FoxFormLabel as="span">정산 계좌</FoxFormLabel>
          <div className={styles.pair}>
            <FoxSelect
              size="md"
              aria-label="입금 은행"
              options={codeTables.bank.map((code) => ({ value: code.code, label: code.label }))}
              value={bankCode}
              onValueChange={setBankCode}
              placeholder="은행 선택"
            />
            <FoxInput
              size="md"
              name="bankHolderName"
              aria-label="예금주명"
              placeholder="예금주명"
              maxLength={OWNER_MAX_LENGTH}
            />
          </div>
          <FoxInput
            size="md"
            name="accountNumber"
            aria-label="입금계좌번호"
            placeholder="입금계좌번호 (숫자와 -)"
            maxLength={ACCOUNT_NUMBER_MAX_LENGTH}
            invalid={Boolean(errors.accountNumber)}
            message={errors.accountNumber}
          />
        </div>

        <div className={styles.field}>
          <FoxFormLabel as="span" requirement="required">
            사용여부
          </FoxFormLabel>
          <FoxRadioGroup name="visibility" size="md" label="사용여부">
            <FoxRadio
              value="Y"
              label="노출"
              checked={isVisible === true}
              onChange={() => setIsVisible(true)}
            />
            <FoxRadio
              value="N"
              label="미노출"
              checked={isVisible === false}
              onChange={() => setIsVisible(false)}
            />
          </FoxRadioGroup>
        </div>

        <div className={styles.field}>
          <FoxInput
            size="md"
            name="memo"
            label="메모"
            defaultValue={merchant?.memo ?? ''}
            placeholder="관리자 메모 (사용자에게 노출되지 않음)"
            maxLength={MEMO_MAX_LENGTH}
          />
        </div>

        {isEdit && (
          <div className={styles.field}>
            <FoxFormLabel as="span">등록일 / 최종수정일</FoxFormLabel>
            <div className={styles.pair}>
              <FoxInput
                size="md"
                aria-label="등록일"
                value={formatOptionalValue(merchant?.createdAt)}
                readOnly
                state="view"
              />
              <FoxInput
                size="md"
                aria-label="최종수정일"
                value={formatOptionalValue(merchant?.updatedAt)}
                readOnly
                state="view"
              />
            </div>
          </div>
        )}
      </form>
    </FoxModal>
  );
}
