import { useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import {
  Alert,
  Button,
  Descriptions,
  Divider,
  Form,
  InputNumber,
  Space,
  Spin,
  Steps,
  Table,
  Tag,
  Typography,
  Input,
} from 'antd';
import type { TableColumnsType } from 'antd';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import { Link, useNavigate, useSearch } from '@tanstack/react-router';
import type { CreatePedido, CreatePedidoItem, ProdutoSummary } from '@sar/api-interface';
import { useClientDetail } from '../../lib/queries/clients';
import { useCatalog } from '../../lib/queries/catalog';
import { apiFetch } from '../../lib/api-client';

const { Title, Text } = Typography;
const { Search } = Input;

type CartItem = CreatePedidoItem & { key: string };

function calcItemTotal(qty: number, price: number, disc: number): number {
  return Math.round(qty * price * (1 - disc / 100) * 100) / 100;
}

function fmt(n: number): string {
  return n.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' });
}

// ─── Step 1 — Selecionar Produtos ────────────────────────────────────────────

function ProductStep({
  cart,
  onAdd,
  onRemove,
  onQtyChange,
  onDiscChange,
}: {
  cart: CartItem[];
  onAdd: (p: ProdutoSummary) => void;
  onRemove: (key: string) => void;
  onQtyChange: (key: string, qty: number) => void;
  onDiscChange: (key: string, disc: number) => void;
}) {
  const [q, setQ] = useState('');
  const { data, isLoading } = useCatalog({ q: q || undefined, limit: 20 });

  const cartKeys = new Set(cart.map((c) => String(c.idProduto)));

  const catalogColumns: TableColumnsType<ProdutoSummary> = [
    { title: 'Código', dataIndex: 'codigo', width: 100 },
    { title: 'Produto', dataIndex: 'descricao', ellipsis: true },
    {
      title: 'Grupo',
      dataIndex: 'grupo',
      width: 110,
      render: (v: string | null) => (v ? <Tag>{v}</Tag> : null),
    },
    {
      title: 'Preço',
      dataIndex: 'vlPreco1',
      width: 110,
      align: 'right',
      render: (v: string) => fmt(Number(v)),
    },
    {
      title: '',
      width: 80,
      render: (_: unknown, row: ProdutoSummary) => (
        <Button
          size="small"
          icon={<PlusOutlined />}
          disabled={cartKeys.has(String(row.idErp))}
          onClick={() => onAdd(row)}
        >
          Add
        </Button>
      ),
    },
  ];

  const cartColumns: TableColumnsType<CartItem> = [
    { title: 'Produto', dataIndex: 'descProduto', ellipsis: true },
    {
      title: 'Qtd',
      dataIndex: 'qtd',
      width: 100,
      render: (v: number, row: CartItem) => (
        <InputNumber
          min={0.001}
          step={1}
          value={v}
          size="small"
          style={{ width: 80 }}
          onChange={(n) => onQtyChange(row.key, n ?? 1)}
        />
      ),
    },
    {
      title: 'Desc %',
      dataIndex: 'descontoPerc',
      width: 100,
      render: (v: number, row: CartItem) => (
        <InputNumber
          min={0}
          max={100}
          step={0.5}
          value={v}
          size="small"
          style={{ width: 80 }}
          onChange={(n) => onDiscChange(row.key, n ?? 0)}
        />
      ),
    },
    {
      title: 'Subtotal',
      width: 120,
      align: 'right',
      render: (_: unknown, row: CartItem) =>
        fmt(calcItemTotal(row.qtd, row.precoUnitario, row.descontoPerc)),
    },
    {
      title: '',
      width: 40,
      render: (_: unknown, row: CartItem) => (
        <Button danger size="small" icon={<DeleteOutlined />} onClick={() => onRemove(row.key)} />
      ),
    },
  ];

  return (
    <Space orientation="vertical" style={{ width: '100%' }} size="middle">
      <Search
        placeholder="Buscar produto por nome ou código..."
        allowClear
        style={{ maxWidth: 400 }}
        onSearch={setQ}
        onChange={(e) => {
          if (!e.target.value) setQ('');
        }}
      />
      <Table<ProdutoSummary>
        rowKey="idErp"
        columns={catalogColumns}
        dataSource={data?.data ?? []}
        loading={isLoading}
        size="small"
        pagination={false}
        scroll={{ y: 220 }}
      />
      <Divider orientation="left">Itens do Pedido ({cart.length})</Divider>
      <Table<CartItem>
        rowKey="key"
        columns={cartColumns}
        dataSource={cart}
        size="small"
        pagination={false}
        locale={{ emptyText: 'Nenhum produto adicionado ainda.' }}
      />
    </Space>
  );
}

// ─── Step 2 — Desconto Global + Observações ───────────────────────────────────

function ReviewStep({
  cart,
  globalDisc,
  obs,
  creditLimit,
  onDiscChange,
  onObsChange,
}: {
  cart: CartItem[];
  globalDisc: number;
  obs: string;
  creditLimit: string | null;
  onDiscChange: (v: number) => void;
  onObsChange: (v: string) => void;
}) {
  const itemsSubtotal = cart.reduce(
    (acc, it) => acc + calcItemTotal(it.qtd, it.precoUnitario, it.descontoPerc),
    0,
  );
  const total = Math.round(itemsSubtotal * (1 - globalDisc / 100) * 100) / 100;
  const limit = creditLimit ? Number(creditLimit) : null;
  const creditOk = limit === null || total <= limit;

  return (
    <Space orientation="vertical" style={{ width: '100%' }} size="middle">
      <Descriptions bordered size="small" column={2}>
        <Descriptions.Item label="Subtotal dos itens" span={2}>
          <Text strong>{fmt(itemsSubtotal)}</Text>
        </Descriptions.Item>
        <Descriptions.Item label="Desconto global do pedido">
          <InputNumber
            min={0}
            max={100}
            step={0.5}
            value={globalDisc}
            addonAfter="%"
            style={{ width: 120 }}
            onChange={(n) => onDiscChange(n ?? 0)}
          />
        </Descriptions.Item>
        <Descriptions.Item label="Total do pedido">
          <Text strong style={{ fontSize: 16 }}>
            {fmt(total)}
          </Text>
        </Descriptions.Item>
        <Descriptions.Item label="Limite de crédito">{limit ? fmt(limit) : '—'}</Descriptions.Item>
        <Descriptions.Item label="Situação crédito">
          <Tag color={creditOk ? 'success' : 'error'}>{creditOk ? 'OK' : 'Acima do limite'}</Tag>
        </Descriptions.Item>
      </Descriptions>

      <Form.Item label="Observações (opcional)">
        <Input.TextArea
          rows={3}
          maxLength={500}
          showCount
          value={obs}
          onChange={(e) => onObsChange(e.target.value)}
          placeholder="Instruções de entrega, referência do comprador, etc."
        />
      </Form.Item>
    </Space>
  );
}

// ─── Step 3 — Confirmação ─────────────────────────────────────────────────────

function ConfirmStep({
  cart,
  globalDisc,
  obs,
  clientNome,
}: {
  cart: CartItem[];
  globalDisc: number;
  obs: string;
  clientNome: string;
}) {
  const itemsSubtotal = cart.reduce(
    (acc, it) => acc + calcItemTotal(it.qtd, it.precoUnitario, it.descontoPerc),
    0,
  );
  const total = Math.round(itemsSubtotal * (1 - globalDisc / 100) * 100) / 100;

  return (
    <Space orientation="vertical" style={{ width: '100%' }} size="middle">
      <Descriptions bordered size="small" column={1}>
        <Descriptions.Item label="Cliente">{clientNome}</Descriptions.Item>
        <Descriptions.Item label="Produtos">{cart.length} item(ns)</Descriptions.Item>
        <Descriptions.Item label="Subtotal dos itens">{fmt(itemsSubtotal)}</Descriptions.Item>
        <Descriptions.Item label="Desconto global">{globalDisc}%</Descriptions.Item>
        <Descriptions.Item label="Total">
          <Text strong style={{ fontSize: 18 }}>
            {fmt(total)}
          </Text>
        </Descriptions.Item>
        {obs && <Descriptions.Item label="Observações">{obs}</Descriptions.Item>}
      </Descriptions>
      <Alert
        type="info"
        message="O pedido será criado como Pendente de Aprovação ou Aprovado conforme a sua alçada de desconto."
        showIcon
      />
    </Space>
  );
}

// ─── NewOrderPage ─────────────────────────────────────────────────────────────

type SearchParams = { clientId?: string };

export function NewOrderPage() {
  const { clientId } = useSearch({ strict: false }) as SearchParams;
  const navigate = useNavigate();
  const qc = useQueryClient();

  const clientIdNum = clientId ? Number(clientId) : undefined;
  const { data: client, isLoading: clientLoading } = useClientDetail(clientIdNum);

  const [step, setStep] = useState(0);
  const [cart, setCart] = useState<CartItem[]>([]);
  const [globalDisc, setGlobalDisc] = useState(0);
  const [obs, setObs] = useState('');
  const [error, setError] = useState<string | null>(null);

  const mutation = useMutation({
    mutationFn: async () => {
      if (!clientIdNum) throw new Error('clientId ausente');
      const body: CreatePedido = {
        idCliente: clientIdNum,
        descontoPerc: globalDisc,
        obs: obs || undefined,
        idempotencyKey: crypto.randomUUID(),
        itens: cart.map((it, idx) => ({
          idProduto: it.idProduto,
          codProduto: it.codProduto,
          descProduto: it.descProduto,
          ordem: idx + 1,
          qtd: it.qtd,
          precoUnitario: it.precoUnitario,
          descontoPerc: it.descontoPerc,
        })),
      };
      return apiFetch('/orders', { method: 'POST', body });
    },
    onSuccess: (pedido: { id: string }) => {
      void qc.invalidateQueries({ queryKey: ['orders'] });
      void qc.invalidateQueries({ queryKey: ['clients', clientIdNum] });
      void navigate({ to: '/pedidos/$id', params: { id: pedido.id } });
    },
    onError: (e: unknown) => setError(e instanceof Error ? e.message : 'Erro ao criar pedido'),
  });

  const addToCart = (p: ProdutoSummary) => {
    setCart((prev) => [
      ...prev,
      {
        key: String(p.idErp),
        idProduto: p.idErp,
        codProduto: p.codigo,
        descProduto: p.descricao,
        ordem: prev.length + 1,
        qtd: 1,
        precoUnitario: Number(p.vlPreco1),
        descontoPerc: 0,
      },
    ]);
  };

  const removeFromCart = (key: string) => setCart((prev) => prev.filter((it) => it.key !== key));
  const setQty = (key: string, qty: number) =>
    setCart((prev) => prev.map((it) => (it.key === key ? { ...it, qtd: qty } : it)));
  const setDisc = (key: string, disc: number) =>
    setCart((prev) => prev.map((it) => (it.key === key ? { ...it, descontoPerc: disc } : it)));

  if (!clientId)
    return <Alert type="error" message="Parâmetro clientId ausente." style={{ margin: 24 }} />;

  if (clientLoading) return <Spin style={{ display: 'block', marginTop: 64 }} />;

  if (!client)
    return <Alert type="error" message="Cliente não encontrado." style={{ margin: 24 }} />;

  const steps = [{ title: 'Produtos' }, { title: 'Desconto / Obs.' }, { title: 'Confirmar' }];

  const canNext = (step === 0 && cart.length > 0) || step === 1;

  return (
    <div style={{ padding: 24, maxWidth: 900 }}>
      <Space align="center" style={{ marginBottom: 16 }}>
        <Link to="/clientes/$id" params={{ id: clientId }}>
          ← {client.razao ?? client.nome}
        </Link>
        <Title level={3} style={{ margin: 0 }}>
          Novo Pedido
        </Title>
      </Space>

      <Steps current={step} items={steps} style={{ marginBottom: 24 }} />

      {step === 0 && (
        <ProductStep
          cart={cart}
          onAdd={addToCart}
          onRemove={removeFromCart}
          onQtyChange={setQty}
          onDiscChange={setDisc}
        />
      )}
      {step === 1 && (
        <ReviewStep
          cart={cart}
          globalDisc={globalDisc}
          obs={obs}
          creditLimit={client.limiteCreditoStr}
          onDiscChange={setGlobalDisc}
          onObsChange={setObs}
        />
      )}
      {step === 2 && (
        <ConfirmStep
          cart={cart}
          globalDisc={globalDisc}
          obs={obs}
          clientNome={client.razao ?? client.nome}
        />
      )}

      {error && (
        <Alert
          type="error"
          message={error}
          showIcon
          style={{ marginTop: 16 }}
          closable
          onClose={() => setError(null)}
        />
      )}

      <Divider />
      <Space>
        {step > 0 && <Button onClick={() => setStep((s) => s - 1)}>Voltar</Button>}
        {step < 2 && (
          <Button type="primary" disabled={!canNext} onClick={() => setStep((s) => s + 1)}>
            Próximo
          </Button>
        )}
        {step === 2 && (
          <Button type="primary" loading={mutation.isPending} onClick={() => mutation.mutate()}>
            Confirmar Pedido
          </Button>
        )}
      </Space>
    </div>
  );
}
