import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {Alert, Badge, Button, Center, Group, Loader, Modal, NumberInput, Paper, Stack, Switch, Text, TextInput, ThemeIcon, Tooltip} from '@mantine/core';
import {
  IconAlertTriangle,
  IconCreditCard,
  IconInfoCircle,
  IconLock,
} from '@tabler/icons-react';
import { AdvancedTable, ModalFooter, notify, PageHeader, PageLoader, useServerTable, type AdvancedColumn } from '@ema-platform/ui';
import {
  extractErrorMessage,
  useLocalized,
  useGetLicenseTypesQuery,
  useGetPaymentCapabilitiesQuery,
  useUpdateLicenseFeesMutation,
} from '@ema-platform/api';
import type { LicenseType } from '@ema-platform/api';
import { paymentConfigColumns } from './columns';
import { paymentConfigActionsColumn } from './actions';

/**
 * Fee configuration — shared across logistics licences, seafarer
 * certificates and seafarer/vessel documents alike.
 *
 * The amounts live on the license type itself, which is what the workflow
 * reads when it raises a payment — so what is edited here is the same value
 * the applicant is charged, not a parallel copy of it.
 *
 * Saving is guarded server-side by `can:update:license-type`; an officer
 * without that permission can read the figures but the save is refused.
 */

export function PaymentConfigPage() {
  const { t } = useTranslation();
  const localized = useLocalized();
  const { data, isLoading, isFetching, error, refetch } =
    useGetLicenseTypesQuery();
  const { data: capabilities } = useGetPaymentCapabilitiesQuery();
  const [editing, setEditing] = useState<LicenseType | null>(null);
  const { setPageIndex, pageSize, setPageSize, paginate } = useServerTable();

  if (isLoading) {
    return <PageLoader label="Loading Payment Configuration…" height={400} />;
  }

  if (error) {
    return (
      <Alert
        color="red"
        icon={<IconAlertTriangle size={18} />}
        title={t('paymentConfig.loadError', 'Could not load fee types')}
      >
        <Text size="sm">{extractErrorMessage(error)}</Text>
      </Alert>
    );
  }

  const types = [...(data?.items ?? [])].sort(
    (a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0),
  );
  const page = paginate(types);

  const columns: AdvancedColumn<LicenseType>[] = [
    ...paymentConfigColumns(t, localized),
    paymentConfigActionsColumn(t, { onEdit: setEditing }),
  ];

  return (
    <Stack gap="lg">
      <PageHeader
        title={t('paymentConfig.title', 'Payment configuration')}
        subtitle={t(
          'paymentConfig.subtitle',
          'What each licence costs. Applicants are charged after approval, and the amount is fixed onto the application at that moment.',
        )}
        noMargin
        action={
          <ThemeIcon size="xl" radius="md" variant="light">
            <IconCreditCard size={22} />
          </ThemeIcon>
        }
      />

      <Alert
        variant="light"
        color="blue"
        radius="md"
        icon={<IconInfoCircle size={18} />}
      >
        <Text size="sm">
          {t(
            'paymentConfig.changeNotice',
            'A change applies to applications approved from now on. Anything already approved keeps the amount it was quoted, so an edit here can never alter what an applicant has already been asked to pay.',
          )}
        </Text>
      </Alert>

      <AdvancedTable
        tableName="payment-config-license-types"
        columns={columns}
        data={page.rows}
        itemCount={page.itemCount}
        pageIndex={page.pageIndex}
        onPageChange={setPageIndex}
        pageSize={pageSize}
        onPageSizeChange={setPageSize}
        refresh={refetch}
        isLoading={isFetching}
      />

      <GatewayPanel bypassEnabled={capabilities?.bypassEnabled} />

      <FeeEditModal licenseType={editing} onClose={() => setEditing(null)} />
    </Stack>
  );
}

/**
 * How payments are actually collected. Read-only on purpose: these come from
 * the payment service's environment rather than the database, so rendering
 * them as editable fields would be a lie.
 */
function GatewayPanel({ bypassEnabled }: { bypassEnabled?: boolean }) {
  const { t } = useTranslation();
  return (
    <Paper withBorder radius="md" p="md">
      <Group gap="xs" mb="xs">
        <ThemeIcon size="sm" radius="xl" variant="light" color="gray">
          <IconLock size={13} />
        </ThemeIcon>
        <Text fw={600} size="sm">
          {t('paymentConfig.gateway.title', 'Payment gateway')}
        </Text>
        <Text size="xs" c="dimmed">
          {t(
            'paymentConfig.gateway.subtitle',
            'Set by the payment service environment — not editable here.',
          )}
        </Text>
      </Group>
      <Group gap="sm">
        <Badge variant="light">{t('paymentConfig.gateway.provider', 'Telebirr')}</Badge>
        {bypassEnabled ? (
          <Tooltip
            label={t(
              'paymentConfig.gateway.bypassTooltip',
              'ALLOW_PAYMENT_BYPASS is on, so an applicant can settle a fee without paying. It is refused in production.',
            )}
          >
            <Badge variant="light" color="orange">
              {t('paymentConfig.gateway.bypassEnabled', 'Test bypass enabled')}
            </Badge>
          </Tooltip>
        ) : (
          <Badge variant="light" color="gray">
            {t('paymentConfig.gateway.bypassOff', 'Test bypass off')}
          </Badge>
        )}
      </Group>
    </Paper>
  );
}

function FeeEditModal({
  licenseType,
  onClose,
}: {
  licenseType: LicenseType | null;
  onClose: () => void;
}) {
  const { t } = useTranslation();
  const localized = useLocalized();
  const [updateFees, { isLoading }] = useUpdateLicenseFeesMutation();
  const [newFee, setNewFee] = useState<number | ''>('');
  const [renewalFee, setRenewalFee] = useState<number | ''>('');
  const [currency, setCurrency] = useState('ETB');
  // Held separately from an empty amount: "carries no fee" and "same as new"
  // are real configuration states, not blank fields.
  const [chargeable, setChargeable] = useState(true);
  const [sameAsNew, setSameAsNew] = useState(true);
  // The examined-certificate stages. Held the same way — null means "this stage
  // is not charged", which is different from a blank box.
  const [eligibilityFee, setEligibilityFee] = useState<number | ''>('');
  const [examinationFee, setExaminationFee] = useState<number | ''>('');
  const [certificateFee, setCertificateFee] = useState<number | ''>('');

  const examined = licenseType?.requiresExamination ?? false;

  useEffect(() => {
    if (!licenseType) return;
    setEligibilityFee(
      licenseType.feeEligibility == null ? '' : Number(licenseType.feeEligibility),
    );
    setExaminationFee(
      licenseType.feeExamination == null ? '' : Number(licenseType.feeExamination),
    );
    setCertificateFee(
      licenseType.feeCertificate == null ? '' : Number(licenseType.feeCertificate),
    );
    setChargeable(licenseType.feeNewApplication !== null);
    setNewFee(
      licenseType.feeNewApplication === null
        ? ''
        : Number(licenseType.feeNewApplication),
    );
    setSameAsNew(licenseType.feeRenewal === null);
    setRenewalFee(
      licenseType.feeRenewal === null ? '' : Number(licenseType.feeRenewal),
    );
    setCurrency(licenseType.feeCurrency || 'ETB');
  }, [licenseType]);

  async function save() {
    if (!licenseType) return;
    if (chargeable && newFee === '') {
      notify.error(
        t(
          'paymentConfig.modal.missingNewFee',
          'Enter a new-application fee, or turn off "carries a fee".',
        ),
      );
      return;
    }
    if (chargeable && !sameAsNew && renewalFee === '') {
      notify.error(
        t(
          'paymentConfig.modal.missingRenewalFee',
          'Enter a renewal fee, or charge renewal at the same rate.',
        ),
      );
      return;
    }
    try {
      await updateFees({
        id: licenseType.id,
        feeNewApplication: chargeable ? Number(newFee) : null,
        feeRenewal: chargeable && !sameAsNew ? Number(renewalFee) : null,
        feeCurrency: currency.trim() || 'ETB',
        // Only sent for examined types; otherwise the columns stay untouched.
        ...(examined
          ? {
              feeEligibility: eligibilityFee === '' ? null : Number(eligibilityFee),
              feeExamination: examinationFee === '' ? null : Number(examinationFee),
              feeCertificate: certificateFee === '' ? null : Number(certificateFee),
            }
          : {}),
      }).unwrap();
      notify.success(
        t('paymentConfig.modal.updated', {
          type: localized(licenseType.name),
          defaultValue: '{{type}} fees updated.',
        }),
      );
      onClose();
    } catch (err) {
      notify.error(
        extractErrorMessage(err, t('paymentConfig.modal.saveFailed', 'Could not save the fees')),
      );
    }
  }

  return (
    <Modal
      opened={!!licenseType}
      onClose={onClose}
      title={
        licenseType
          ? t('paymentConfig.modal.title', {
              type: localized(licenseType.name),
              defaultValue: 'Fees — {{type}}',
            })
          : ''
      }
      centered
      radius="lg"
    >
      {licenseType && (
        <Stack gap="md">
          {!licenseType.issuesCertificate && (
            <Alert
              variant="light"
              color="gray"
              icon={<IconInfoCircle size={16} />}
            >
              <Text size="sm">
                {t(
                  'paymentConfig.modal.noPaymentStage',
                  'This licence type concludes with an EMA decision and never reaches a payment stage, so a fee set here stays unused until that changes.',
                )}
              </Text>
            </Alert>
          )}

          <Switch
            checked={chargeable}
            onChange={(e) => setChargeable(e.currentTarget.checked)}
            label={t('paymentConfig.modal.chargeableLabel', 'This licence carries a fee')}
            description={t(
              'paymentConfig.modal.chargeableDescription',
              'Turn off for licence types applicants are never charged for.',
            )}
          />

          {chargeable && (
            <>
              <NumberInput
                label={t('paymentConfig.modal.newFeeLabel', 'New application fee')}
                value={newFee}
                onChange={(v) => setNewFee(v === '' ? '' : Number(v))}
                min={0}
                max={9_999_999_999}
                thousandSeparator=","
                allowNegative={false}
                decimalScale={2}
              />

              <Switch
                checked={sameAsNew}
                onChange={(e) => setSameAsNew(e.currentTarget.checked)}
                label={t('paymentConfig.modal.sameRateLabel', 'Charge renewal at the same rate')}
                description={t(
                  'paymentConfig.modal.sameRateDescription',
                  'Turn off to set a separate renewal fee.',
                )}
              />

              {!sameAsNew && (
                <NumberInput
                  label={t('paymentConfig.modal.renewalFeeLabel', 'Renewal fee')}
                  value={renewalFee}
                  onChange={(v) => setRenewalFee(v === '' ? '' : Number(v))}
                  min={0}
                  max={9_999_999_999}
                  thousandSeparator=","
                  allowNegative={false}
                  decimalScale={2}
                />
              )}

              <TextInput
                label={t('paymentConfig.modal.currencyLabel', 'Currency')}
                value={currency}
                onChange={(e) =>
                  setCurrency(e.currentTarget.value.toUpperCase())
                }
                maxLength={8}
              />
            </>
          )}

          {examined && (
            <>
              <Alert
                variant="light"
                color="blue"
                icon={<IconInfoCircle size={16} />}
              >
                <Text size="sm">
                  {t(
                    'paymentConfig.modal.examinedNotice',
                    'This certificate is earned by examination, so it is charged in three stages. Unlike the fees above, these are not fixed at approval — a change applies to candidates already part-way through. Clearing one while candidates are waiting to pay it will be refused.',
                  )}
                </Text>
              </Alert>

              <NumberInput
                label={t('paymentConfig.modal.eligibilityFeeLabel', 'Eligibility assessment fee')}
                description={t(
                  'paymentConfig.modal.eligibilityFeeHint',
                  'Due on submission, before an officer reviews the application. Leave empty for no charge.',
                )}
                value={eligibilityFee}
                onChange={(v) => setEligibilityFee(v === '' ? '' : Number(v))}
                min={0}
                max={9_999_999_999}
                thousandSeparator=","
                allowNegative={false}
                decimalScale={2}
              />

              <NumberInput
                label={t('paymentConfig.modal.examinationFeeLabel', 'Examination fee')}
                description={t(
                  'paymentConfig.modal.examinationFeeHint',
                  'Due once eligibility is approved, and again for a retake.',
                )}
                value={examinationFee}
                onChange={(v) => setExaminationFee(v === '' ? '' : Number(v))}
                min={0}
                max={9_999_999_999}
                thousandSeparator=","
                allowNegative={false}
                decimalScale={2}
              />

              <NumberInput
                label={t('paymentConfig.modal.certificateFeeLabel', 'Certificate fee')}
                description={t(
                  'paymentConfig.modal.certificateFeeHint',
                  'Due after a pass, before the certificate is issued.',
                )}
                value={certificateFee}
                onChange={(v) => setCertificateFee(v === '' ? '' : Number(v))}
                min={0}
                max={9_999_999_999}
                thousandSeparator=","
                allowNegative={false}
                decimalScale={2}
              />
            </>
          )}

          <ModalFooter mt="xs">
            <Button variant="default" onClick={onClose} disabled={isLoading}>
              {t('paymentConfig.modal.cancel', 'Cancel')}
            </Button>
            <Button onClick={save} loading={isLoading}>
              {t('paymentConfig.modal.save', 'Save fees')}
            </Button>
          </ModalFooter>
        </Stack>
      )}
    </Modal>
  );
}

export default PaymentConfigPage;
