'use client';

/**
 * Público-alvo e tom de comunicação do site (`/projetos/[id]/software/publico-alvo-tom`).
 * FRONT-S2-02 — extraído de `app/(dashboard)/projetos/[id]/software/publico-alvo-tom/page.tsx`.
 */

import { MessageSquare, Save, Settings2, Users } from 'lucide-react';
import { ICON_SIZE_MD, ICON_SIZE_SM } from '@/components/icons';
import React, { useEffect, useMemo } from 'react';
import Link from 'next/link';
import { useParams } from 'next/navigation';
import { Form, Button, Spin, Divider, Tag, Typography } from 'antd';
import { message } from '@/lib/feedback/message';
import { notifyApiError } from '@/lib/feedback/notifyApiError';
import { FormTextarea } from '@/components/form';
import { FormActions as FormActionsWrapper } from '@/components/form';
import { useIsMobile } from '@/hooks/useIsMobile';
import { useQueryCache } from '@/hooks/useQueryCache';
import { useMutationCache } from '@/hooks/useMutationCache';
import { queryKeys } from '@/lib/cache/queryKeys';
import { API_ENDPOINTS } from '@/lib/api/endpoints';
import { Projeto } from '@/types';
import ProjetoLayout from '@/components/layouts/ProjetoLayout';
import ContentCard from '@/components/layouts/ContentCard';
import { useMobilePageActionBarRegistration } from '@/components/layouts/PageShellOptions';
import { projetosParametrosPaths } from '@/lib/routes/projetosParametrosPaths';
import { routeProjetoId } from '@/features/projetos/feira-list';
import { useProjetoBriefingFormGuard } from '@/features/projetos/hooks/useProjetoBriefingFormGuard';
import { useRegisterPlanejamentoWizardSave } from '@/components/layouts/ProjetoLayout/ProjetoPlanejamentoWizardContext';
import type { FormInstance } from 'antd';
import { BriefingOpcaoChipGroup } from './BriefingOpcaoChipGroup';
import styles from './ProjetoSoftwarePublicoAlvoTomScreen.module.scss';
import {
    ProjetoTipologicoSyncBanner,
    TIPOLOGICO_EMPTY_DOMAIN,
} from '@/features/projetos/projeto-tipologico-empty-state';

const { Text } = Typography;

function PublicoAlvoPlanejamentoWizardSaveBridge({
    form,
    saving,
    onPersist,
}: {
    form: FormInstance;
    saving: boolean;
    onPersist: (values: {
        publico_alvo_opcoes?: number[];
        publico_alvo?: string;
        tom_opcoes?: number[];
        tom_comunicacao?: string;
    }) => Promise<unknown>;
}) {
    useRegisterPlanejamentoWizardSave({
        enabled: true,
        canSave: !saving,
        saving,
        saveLabel: 'Salvar',
        onSave: async () => {
            const values = await form.validateFields();
            await onPersist(values);
        },
    });
    return null;
}

const MAX_CHARS = 10000;

interface OpcaoItem {
    id: number;
    nome: string;
    codigo?: string | null;
    ativo?: boolean;
    ordem?: number;
}

function buildCheckboxOptions(
    raw: { data?: OpcaoItem[] } | OpcaoItem[] | undefined
): { label: string; value: number }[] {
    const list = Array.isArray(raw) ? raw : Array.isArray(raw?.data) ? raw.data : [];
    return list
        .filter((o) => o && typeof o === 'object' && o.ativo !== false)
        .sort((a, b) => (a.ordem ?? 0) - (b.ordem ?? 0))
        .map((o) => ({ label: String(o.nome ?? ''), value: Number(o.id) }));
}

export function ProjetoSoftwarePublicoAlvoTomScreen() {
    const params = useParams();
    const id = routeProjetoId(params);
    const isMobileLayout = useIsMobile();
    /** Sticky «Salvar» no rodapé mobile — form longo (TASK-APR-048 / AR-OP-017). */
    useMobilePageActionBarRegistration(isMobileLayout);
    const [form] = Form.useForm();
    const publicoAlvoSelecionados =
        (Form.useWatch('publico_alvo_opcoes', form) as number[] | undefined) ?? [];
    const tomSelecionados = (Form.useWatch('tom_opcoes', form) as number[] | undefined) ?? [];
    const {
        draftBanner,
        savedHint,
        handleFormValuesChange,
        afterSaveSuccess,
        handleCancelEdits,
    } = useProjetoBriefingFormGuard(form, id, 'publico-alvo-tom');

    const { data: projetoResponse, isLoading: isLoadingProjeto } = useQueryCache<
        Projeto | { projeto?: Projeto; metricas?: unknown }
    >({
        queryKey: queryKeys.projetos.detail(id),
        endpoint: API_ENDPOINTS.projetos.show(id),
        enabled: !!id,
        staleTime: 1 * 60 * 1000,
        gcTime: 5 * 60 * 1000});

    const paramsAll = useMemo(() => ({ per_page: 'all' as const }), []);

    const { data: publicosAlvoData } = useQueryCache<{ data: OpcaoItem[] } | OpcaoItem[]>({
        queryKey: queryKeys.projetoPublicosAlvo.lists(),
        endpoint: API_ENDPOINTS.projetoPublicosAlvo.index,
        params: paramsAll,
        staleTime: 5 * 60 * 1000,
        enabled: true});

    const { data: tonsData } = useQueryCache<{ data: OpcaoItem[] } | OpcaoItem[]>({
        queryKey: queryKeys.projetoTonsComunicacao.lists(),
        endpoint: API_ENDPOINTS.projetoTonsComunicacao.index,
        params: paramsAll,
        staleTime: 5 * 60 * 1000,
        enabled: true});

    const projeto =
        projetoResponse && typeof projetoResponse === 'object' && 'projeto' in projetoResponse
            ? (projetoResponse as { projeto?: Projeto }).projeto
            : (projetoResponse as Projeto | undefined);

    const publicoAlvoOpcoes = useMemo(
        () => buildCheckboxOptions(publicosAlvoData as { data?: OpcaoItem[] } | OpcaoItem[] | undefined),
        [publicosAlvoData]
    );

    const tomOpcoes = useMemo(
        () => buildCheckboxOptions(tonsData as { data?: OpcaoItem[] } | OpcaoItem[] | undefined),
        [tonsData]
    );

    const updateMutation = useMutationCache({
        endpoint: API_ENDPOINTS.projetos.update(id),
        method: 'PUT',
        invalidateQueries: [queryKeys.projetos.detail(id), queryKeys.projetos.lists()],
        onSuccess: () => {
            message.success('Público-alvo e tom de comunicação salvos com sucesso!');
            afterSaveSuccess();
        },
        onError: (error: unknown) => {
            notifyApiError(error, 'Erro ao salvar público-alvo e tom.', 'generic');
        }});

    /** LOG-026: deps primitivas + skip se igual/dirty — evita React #185 (Maximum update depth). */
    const projetoId = projeto?.id;
    const publicoAlvoServer = projeto?.publico_alvo ?? '';
    const tomComunicacaoServer = projeto?.tom_comunicacao ?? '';
    const publicoAlvoOpcoesKey = JSON.stringify(projeto?.publico_alvo_opcoes ?? []);
    const tomOpcoesKey = JSON.stringify(projeto?.tom_opcoes ?? []);
    useEffect(() => {
        if (projetoId == null) return;
        const next = {
            publico_alvo_opcoes: JSON.parse(publicoAlvoOpcoesKey) as number[],
            publico_alvo: publicoAlvoServer,
            tom_opcoes: JSON.parse(tomOpcoesKey) as number[],
            tom_comunicacao: tomComunicacaoServer,
        };
        const cur = form.getFieldsValue([
            'publico_alvo_opcoes',
            'publico_alvo',
            'tom_opcoes',
            'tom_comunicacao',
        ]) as {
            publico_alvo_opcoes?: number[];
            publico_alvo?: string;
            tom_opcoes?: number[];
            tom_comunicacao?: string;
        };
        const same =
            JSON.stringify(cur.publico_alvo_opcoes ?? []) === publicoAlvoOpcoesKey &&
            String(cur.publico_alvo ?? '') === publicoAlvoServer &&
            JSON.stringify(cur.tom_opcoes ?? []) === tomOpcoesKey &&
            String(cur.tom_comunicacao ?? '') === tomComunicacaoServer;
        if (same) return;
        if (form.isFieldsTouched()) return;
        form.setFieldsValue(next);
    }, [
        projetoId,
        publicoAlvoServer,
        tomComunicacaoServer,
        publicoAlvoOpcoesKey,
        tomOpcoesKey,
        form,
    ]);

    const handleSubmit = (values: {
        publico_alvo_opcoes?: number[];
        publico_alvo?: string;
        tom_opcoes?: number[];
        tom_comunicacao?: string;
    }) => {
        updateMutation.mutate({
            publico_alvo_opcoes: values.publico_alvo_opcoes?.length ? values.publico_alvo_opcoes : null,
            publico_alvo: values.publico_alvo?.trim() || null,
            tom_opcoes: values.tom_opcoes?.length ? values.tom_opcoes : null,
            tom_comunicacao: values.tom_comunicacao?.trim() || null});
    };

    const isLoading = isLoadingProjeto && !projeto;

    if (isLoading) {
        return (
            <ProjetoLayout
                projetoId={id}
                pageTitle="Público-alvo e tom"
                pageIcon="users"
                titleSection="Público-alvo e tom de comunicação"
            >
                <div style={{ textAlign: 'center', padding: 50 }}>
                    <Spin size="large" />
                </div>
            </ProjetoLayout>
        );
    }

    const initialValues = {
        publico_alvo_opcoes: projeto?.publico_alvo_opcoes ?? [],
        publico_alvo: projeto?.publico_alvo ?? '',
        tom_opcoes: projeto?.tom_opcoes ?? [],
        tom_comunicacao: projeto?.tom_comunicacao ?? ''};

    const publicoAlvoTomVazio =
        !String(projeto?.publico_alvo ?? '').trim() &&
        !(projeto?.publico_alvo_opcoes?.length) &&
        !String(projeto?.tom_comunicacao ?? '').trim() &&
        !(projeto?.tom_opcoes?.length);

    return (
        <ProjetoLayout
            projetoId={id}
            pageTitle="Público-alvo e tom de comunicação"
            pageIcon="users"
            titleSection="Público-alvo e tom de comunicação"
            breadcrumbItems={[
                { title: 'PROJETO' },
                { title: projeto?.nome || 'Projeto' },
                { title: 'Público-alvo e tom' },
            ]}
        >
            {draftBanner}
            {savedHint}

            {publicoAlvoTomVazio ? (
                <ProjetoTipologicoSyncBanner
                    projetoId={id}
                    title="Público-alvo e tom ainda vazios"
                    domainDescription={TIPOLOGICO_EMPTY_DOMAIN.publicoAlvoTom}
                    data-testid="projeto-publico-alvo-sync-banner"
                />
            ) : null}

            {isMobileLayout ? (
                <PublicoAlvoPlanejamentoWizardSaveBridge
                    form={form}
                    saving={updateMutation.isPending}
                    onPersist={async (values) =>
                        updateMutation.mutateAsync({
                            publico_alvo_opcoes: values.publico_alvo_opcoes?.length
                                ? values.publico_alvo_opcoes
                                : null,
                            publico_alvo: values.publico_alvo?.trim() || null,
                            tom_opcoes: values.tom_opcoes?.length ? values.tom_opcoes : null,
                            tom_comunicacao: values.tom_comunicacao?.trim() || null,
                        })
                    }
                />
            ) : null}

            <Form
                form={form}
                layout="vertical"
                initialValues={initialValues}
                onFinish={handleSubmit}
                onValuesChange={handleFormValuesChange}
            >
                <ContentCard
                    title="Público-alvo"
                    icon={<Users size={ICON_SIZE_MD} style={{ marginRight: 8 }} aria-hidden />}
                    style={{ marginBottom: 24 }}
                    headerActions={
                        <Link href={projetosParametrosPaths.publicosAlvo}>
                            <Button
                                type="link"
                                size="small"
                                className={styles.headerLink}
                                icon={<Settings2 size={ICON_SIZE_SM} aria-hidden />}
                            >
                                Gerenciar opções
                            </Button>
                        </Link>
                    }
                >
                    <Text type="secondary" className={styles.intro}>
                        Quem deve ser impactado pelo sistema? Selecione opções do catálogo e complemente
                        com contexto (faixa etária, dores, decisores).
                    </Text>

                    <div className={styles.section}>
                        <div className={styles.sectionHeader}>
                            <p className={styles.sectionTitle}>Opções do catálogo</p>
                            {publicoAlvoSelecionados.length > 0 ? (
                                <Tag color="blue">
                                    {publicoAlvoSelecionados.length} selecionado
                                    {publicoAlvoSelecionados.length === 1 ? '' : 's'}
                                </Tag>
                            ) : null}
                        </div>
                        <div className={styles.optionsPanel}>
                            <Form.Item name="publico_alvo_opcoes" className={styles.formItemFlush}>
                                <BriefingOpcaoChipGroup
                                    options={publicoAlvoOpcoes}
                                    emptyDescription="Nenhum público-alvo cadastrado no catálogo."
                                    emptyCtaHref={projetosParametrosPaths.publicosAlvo}
                                    emptyCtaLabel="Cadastrar público-alvo"
                                    aria-label="Opções de público-alvo"
                                />
                            </Form.Item>
                        </div>
                    </div>

                    <Divider className={styles.divider} />

                    <FormTextarea
                        name="publico_alvo"
                        label="Complemento (opcional)"
                        rules={[
                            {
                                max: MAX_CHARS,
                                message: `Máximo ${MAX_CHARS.toLocaleString('pt-BR')} caracteres.`,
                            },
                        ]}
                        placeholder="Ex.: Faixa etária 25–55 anos; decisores que buscam soluções digitais; principais dores: falta de tempo, necessidade de resultados rápidos."
                        rows={5}
                        maxLength={MAX_CHARS}
                        showCount
                    />
                </ContentCard>

                <ContentCard
                    title="Tom de comunicação"
                    icon={<MessageSquare size={ICON_SIZE_MD} style={{ marginRight: 8 }} aria-hidden />}
                    style={{ marginBottom: 24 }}
                    headerActions={
                        <Link href={projetosParametrosPaths.tonsComunicacao}>
                            <Button
                                type="link"
                                size="small"
                                className={styles.headerLink}
                                icon={<Settings2 size={ICON_SIZE_SM} aria-hidden />}
                            >
                                Gerenciar opções
                            </Button>
                        </Link>
                    }
                >
                    <Text type="secondary" className={styles.intro}>
                        Como a marca deve falar com esse público? Combine o tom do catálogo com
                        orientações de redação e estilo.
                    </Text>

                    <div className={styles.section}>
                        <div className={styles.sectionHeader}>
                            <p className={styles.sectionTitle}>Opções do catálogo</p>
                            {tomSelecionados.length > 0 ? (
                                <Tag color="blue">
                                    {tomSelecionados.length} selecionado
                                    {tomSelecionados.length === 1 ? '' : 's'}
                                </Tag>
                            ) : null}
                        </div>
                        <div className={styles.optionsPanel}>
                            <Form.Item name="tom_opcoes" className={styles.formItemFlush}>
                                <BriefingOpcaoChipGroup
                                    options={tomOpcoes}
                                    emptyDescription="Nenhum tom de comunicação cadastrado no catálogo."
                                    emptyCtaHref={projetosParametrosPaths.tonsComunicacao}
                                    emptyCtaLabel="Cadastrar tom"
                                    aria-label="Opções de tom de comunicação"
                                />
                            </Form.Item>
                        </div>
                    </div>

                    <Divider className={styles.divider} />

                    <FormTextarea
                        name="tom_comunicacao"
                        label="Complemento (opcional)"
                        rules={[
                            {
                                max: MAX_CHARS,
                                message: `Máximo ${MAX_CHARS.toLocaleString('pt-BR')} caracteres.`,
                            },
                        ]}
                        placeholder={
                            'Ex.: linguagem clara, sem jargão excessivo; tom de parceria e confiança. Evitar formalidade excessiva; tratamento de "você" conforme a marca.'
                        }
                        rows={5}
                        maxLength={MAX_CHARS}
                        showCount
                    />
                </ContentCard>

                {!isMobileLayout ? (
                    <FormActionsWrapper>
                        <Button
                            type="default"
                            onClick={() => handleCancelEdits(initialValues)}
                            disabled={updateMutation.isPending || !form.isFieldsTouched()}
                        >
                            Cancelar
                        </Button>
                        <Button
                            type="primary"
                            htmlType="submit"
                            loading={updateMutation.isPending}
                            icon={<Save size={ICON_SIZE_MD} aria-hidden />}
                            data-testid="projeto-publico-alvo-salvar"
                        >
                            Salvar público-alvo e tom
                        </Button>
                    </FormActionsWrapper>
                ) : null}
            </Form>
        </ProjetoLayout>
    );
}
