'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 type { CommonCode } from '@/lib/domain/common-code';
import {
  formatOptionalValue,
  type Merchant,
} from '@/lib/domain/merchant';
import {
  ADDRESS_DETAIL_MAX_LENGTH,
  BRAND_MAX_LENGTH,
  INITIAL_MERCHANT_FORM_STATE,
  MEMO_MAX_LENGTH,
  NAME_MAX_LENGTH,
  OWNER_MAX_LENGTH,
} from '@/lib/domain/merchant-form';
import { saveMerchantAction } from '../_actions';
import { openPostcodeSearch } from './postcode';
import styles from './merchant-form.module.scss';

/**
 * 백엔드에 가맹점 수정 API가 없어(`/api/v1/mngr/voc`는 목록·등록뿐) 수정 모달을 조회
 * 전용으로 연다. **API가 생기면 이 한 줄만 `true`로 바꾸면 된다** — 입력칸·저장 버튼이
 * 전부 이 값에 걸려 있고 폼 자체는 그대로 살아 있다.
 */
const IS_EDIT_ENABLED = false;

interface MerchantFormModalProps {
  merchant?: Merchant;
  /** 업종 코드표 — 선택지이자 조회 전용일 때의 이름 출처. */
  businessCodes: CommonCode[];
  onClose: () => void;
}

export function MerchantFormModal({ merchant, businessCodes, onClose }: MerchantFormModalProps) {
  const isEdit = Boolean(merchant);
  const isReadOnly = isEdit && !IS_EDIT_ENABLED;
  // 조회 전용일 때 입력칸마다 얹는다. `state="view"`는 시안의 조회 상태로, 잠긴 것(disabled)과
  // 달리 "볼 수만 있는 값"으로 보이게 한다.
  const viewProps = isReadOnly ? ({ readOnly: true, state: 'view' } as const) : null;
  const { showToast } = useFeedback();
  const formRef = useRef<HTMLFormElement>(null);
  const [state, formAction, isPending] = useActionState(
    saveMerchantAction,
    INITIAL_MERCHANT_FORM_STATE
  );

  const [categoryCode, setCategoryCode] = useState(merchant?.categoryCode ?? '');
  // 조회 응답에 useYn이 없어 기존 가맹점은 값을 모른다 — 그때는 어느 쪽도 고르지 않는다.
  // 신규 등록만 「노출」로 시작한다.
  const [isVisible, setIsVisible] = useState<boolean | null>(
    merchant === undefined ? true : merchant.isVisible
  );
  // 주소·좌표는 검색 결과가 채운다(기획 ③ Read Only).
  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={isReadOnly ? '가맹점 정보' : isEdit ? '가맹점 수정' : '가맹점 등록'}
      onClose={onClose}
      actions={
        isReadOnly ? (
          <FoxButton type="default" size="md" label="닫기" onAction={onClose} />
        ) : (
          <>
            <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="isVisible" value={isVisible ? 'Y' : 'N'} />
        <input type="hidden" name="address" value={address} />
        <input type="hidden" name="postalCode" value={postalCode} />
        <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
            {...viewProps}
            size="md"
            name="brandName"
            label="브랜드명"
            defaultValue={merchant?.brandName ?? ''}
            placeholder="브랜드명을 입력하세요."
            maxLength={BRAND_MAX_LENGTH}
          />
        </div>

        <div className={styles.field}>
          <FoxInput
            {...viewProps}
            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}>
          <FoxSelect
            readOnly={isReadOnly}
            size="md"
            label="업종"
            requirement="required"
            options={businessCodes.map((code) => ({ value: code.code, label: code.label }))}
            value={categoryCode}
            onValueChange={setCategoryCode}
            placeholder="선택"
            error={Boolean(errors.categoryCode)}
            hint={errors.categoryCode}
          />
        </div>

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

        <div className={styles.field}>
          <FoxInput
            {...viewProps}
            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"
              aria-label="주소"
              value={address}
              readOnly
              state="view"
              placeholder="주소 검색을 진행해주세요."
            />
            {!isReadOnly && (
              <FoxButton
                type="secondary"
                size="md"
                label={isSearching ? '검색 중...' : '주소 검색'}
                disabled={isSearching}
                onAction={searchAddress}
              />
            )}
          </div>
          <FoxInput
            {...viewProps}
            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" requirement="required">
            사용여부
          </FoxFormLabel>
          <FoxRadioGroup name="visibility" size="md" label="사용여부">
            <FoxRadio
              disabled={isReadOnly}
              value="Y"
              label="노출"
              checked={isVisible === true}
              onChange={() => setIsVisible(true)}
            />
            <FoxRadio
              disabled={isReadOnly}
              value="N"
              label="미노출"
              checked={isVisible === false}
              onChange={() => setIsVisible(false)}
            />
          </FoxRadioGroup>
        </div>

        <div className={styles.field}>
          <FoxInput
            {...viewProps}
            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>
  );
}
