import React, { useState, useEffect } from 'react';
import MarkdownRenderer from '@/components/markdown-render';
import { useGetApi } from '@/hooks/use-get-api';
import { GetCuestionario } from '@/types/evento';
import SimpleInput from '@/components/input';
import RadioOptionGroup, { RadioOption } from '@/components/radio-option-group';
import axiosInstance from '@/utils/api-config';
import PrefetchAbiertaCorta from './prefetch-abierta-corta';
import Button from '@/components/button';
import toast from 'react-hot-toast';
import { useRouter } from 'next/navigation';
import { getAxiosError } from '@/utils/errors-utils';

export type UsuarioDataResponse = {
  cuenta: string | null;
  nombre: string | null;
  apellidos: string | null;
  carrera: string | null;
  genero: string | null;
  rfc?: string | null; // Solo para trabajadores
};

type UsuarioData = {
  nombre: string; // alumno o trabajador
  apellidos: string; // alumno o trabajador
  correo: string; // alumno o trabajador (en los alumnos se usa el id_ncuenta en trabajadores ellos deben escribirlo)
  genero: 'M' | 'F'; // alumno o trabajador
  carrera: string; // solo para alumnos
  rfc?: string; // solo para trabajadores se usa para buscar información de cuenta
};

const confirmativeOption = ['Sí', 'Si', 'Si, claro', 'Claro que sí'];
const negativeOption = ['No', 'No, gracias', 'No, de momento'];

type RespuestaFormulario = Record<string, string | number>; // id_pregunta: respuesta

export default function FormularioRegistro({
  id_cuestionario,
}: {
  id_cuestionario: number;
}) {
  // ------------------------
  // Estados
  // ------------------------
  const [isComunidad, setIsComunidad] = useState<RadioOption<number>>();
  const [respuestas, setRespuestas] = useState<RespuestaFormulario>({});
  const [cuentaInfo, setCuentaInfo] = useState<UsuarioData | null>(null);
  const [isSending, setIsSending] = useState(false);
  const router = useRouter();

  // ------------------------
  // Carga del cuestionario
  // ------------------------
  const { data, error } = useGetApi<GetCuestionario>(
    `/cuestionario/${id_cuestionario}/formulario`
  );
  // ------------------------
  // Extracción de preguntas clave
  // ------------------------
  const preguntas = data?.cuestionario.secciones.flatMap((seccion) =>
    seccion.preguntas.map((pregunta) => pregunta.pregunta)
  );

  const preguntaComunidad = preguntas?.find(
    (pregunta) =>
      pregunta.validacion === 'comunidad_alumno' ||
      pregunta.validacion === 'comunidad_trabajador'
  );

  const preguntaCuenta = preguntas?.find(
    (pregunta) =>
      pregunta.validacion === 'cuenta_alumno' ||
      pregunta.validacion === 'cuenta_trabajador' ||
      pregunta.validacion === 'rfc'
  );

  // ------------------------
  // Efecto: buscar información de cuenta
  // ------------------------
  useEffect(() => {
    const cuenta = respuestas[preguntaCuenta?.id_pregunta ?? ''];

    const esCuentaAlumno = preguntaCuenta?.validacion === 'cuenta_alumno';
    const esCuentaTrabajador =
      preguntaCuenta?.validacion === 'cuenta_trabajador' ||
      preguntaCuenta?.validacion === 'rfc';

    const puedeBuscar =
      cuenta &&
      typeof cuenta === 'string' &&
      ((esCuentaAlumno && cuenta.length === 9) ||
        (esCuentaTrabajador && cuenta.length === 10));

    const fetchCuentaInfo = async () => {
      try {
        const endpoint = esCuentaAlumno
          ? `/alumnos/${cuenta}`
          : `/trabajadores/${cuenta}`;

        const res = await axiosInstance.get<UsuarioDataResponse>(endpoint);

        console.log('Datos de cuenta obtenidos:', res.data);
        setCuentaInfo({
          nombre: res.data.nombre ? res.data.nombre : '',
          apellidos: res.data.apellidos ? res.data.apellidos : '',
          correo: res.data.cuenta
            ? `${res.data.cuenta}@pcpuma.acatlan.unam.mx`
            : '',
          genero:
            res.data.genero === 'M' || res.data.genero === 'F'
              ? res.data.genero
              : 'M',
          carrera: res.data.carrera ? res.data.carrera : '',
        });
        // Usar datos fake para pruebas
        /* setCuentaInfo({
          nombre: 'Juan',
          apellidos: 'Pérez',
          correo: 'juan.perez@pcpuma.acatlan.unam.mx',
          genero: 'M',
          carrera: 'Ingeniería en Computación',
        }); */
      } catch (error) {
        console.error('Error al obtener datos de cuenta:', error);
        setCuentaInfo(null);
      }
    };

    if (puedeBuscar) {
      fetchCuentaInfo();
    } else {
      setCuentaInfo(null);
    }
  }, [respuestas[preguntaCuenta?.id_pregunta ?? '']]);

  // ------------------------
  // Efecto: precargar respuestas si hay cuentaInfo
  // ------------------------
  useEffect(() => {
    if (!cuentaInfo) {
      if (preguntas) {
        const idsPrefetch = preguntas
          .filter((pregunta) =>
            [
              'nombre',
              'apellidos',
              'correo',
              'institucion',
              'carrera',
              'genero',
            ].includes(pregunta.validacion)
          )
          .map((pregunta) => pregunta.id_pregunta);

        setRespuestas((prev) => {
          const nuevas = { ...prev };
          idsPrefetch.forEach((id) => {
            delete nuevas[id];
          });
          return nuevas;
        });
      }
      return;
    }

    const nuevasRespuestas: RespuestaFormulario = {};

    if (preguntas) {
      for (const pregunta of preguntas) {
        const id = pregunta.id_pregunta;
        switch (pregunta.validacion) {
          case 'nombre':
            nuevasRespuestas[id] = cuentaInfo.nombre;
            break;
          case 'apellidos':
            nuevasRespuestas[id] = cuentaInfo.apellidos;
            break;
          case 'correo':
            nuevasRespuestas[id] = cuentaInfo.correo;
            break;
          case 'institucion':
            nuevasRespuestas[id] = 'FES Acatlán';
            break;
          case 'carrera':
            nuevasRespuestas[id] = cuentaInfo.carrera;
            break;
          case 'genero':
            const generoTexto =
              cuentaInfo.genero === 'M' ? 'Masculino' : 'Femenino';
            const opcion = pregunta.opciones?.find(
              (op) =>
                op.opcion.opcion.toLowerCase() === generoTexto.toLowerCase()
            );
            if (opcion) {
              nuevasRespuestas[id] = String(opcion.id_opcion);
            }
            break;
        }
      }

      setRespuestas((prev) => ({
        ...prev,
        ...nuevasRespuestas,
      }));
    }
  }, [cuentaInfo]);

  // ------------------------
  // Funciones auxiliares
  // ------------------------
  const actualizarRespuesta = (idPregunta: string, valor: string) => {
    setRespuestas((prev) => ({ ...prev, [idPregunta]: valor }));
  };

  const handleOnSubmit = async () => {
    console.log('Enviando respuestas:', respuestas);
    setIsSending(true);
    if (!data?.cuestionario.id_cuestionario) {
      alert('No se ha cargado correctamente el formulario');
      return;
    }

    const preguntasObligatorias =
      data?.cuestionario.secciones.flatMap((seccion) =>
        seccion.preguntas
          .filter((pregunta) => pregunta.pregunta.obligatoria)
          .map((pregunta) => pregunta.pregunta)
      ) || [];

    const faltantes = preguntasObligatorias.filter(
      (pregunta) =>
        respuestas[pregunta.id_pregunta] === undefined ||
        respuestas[pregunta.id_pregunta] === '' ||
        respuestas[pregunta.id_pregunta] === null
    );

    const preguntaCorreo = preguntasObligatorias.find(
      (pregunta) =>
        pregunta.validacion === 'correo' ||
        pregunta.validacion === 'correo_institucional'
    );

    if (faltantes.length > 0) {
      toast.error('Por favor responde todas las preguntas obligatorias.');
      return;
    }

    // Buscar un posible correo en las respuestas si no hay cuentaInfo
    let correo =
      cuentaInfo?.correo === respuestas[preguntaCorreo?.id_pregunta ?? '']
        ? cuentaInfo?.correo
        : respuestas[preguntaCorreo?.id_pregunta ?? ''];

    if (!correo) {
      // Buscar en las respuestas una que parezca correo
      const correoRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      for (const valor of Object.values(respuestas)) {
        if (typeof valor === 'string' && correoRegex.test(valor)) {
          correo = valor;
          break;
        }
      }
    }

    const payload = {
      id_cuestionario: id_cuestionario,
      correo: correo || '',
      fecha_envio: new Date().toISOString(),
      respuestas: Object.entries(respuestas).map(([id_pregunta, valor]) => ({
        id_pregunta: Number(id_pregunta),
        valor: isNaN(Number(valor)) ? valor : Number(valor),
      })),
    };

    try {
      const res = await axiosInstance.post(
        '/cuestionario-respondido/submit',
        payload
      );
      toast.success(res.data.message || 'Formulario enviado correctamente');
    } catch (error) {
      console.log(getAxiosError(error));
      toast.error('Hubo un error al enviar el formulario');
    } finally {
      // Redirigir al usuario después de enviar el formulario
      router.push('/');
    }
  };

  // ------------------------
  // Condición para mostrar el formulario
  // ------------------------
  const mostrarFormularioRestante =
    (isComunidad &&
      confirmativeOption.some((opt) =>
        isComunidad.label?.toLowerCase().includes(opt.toLowerCase())
      ) &&
      !!cuentaInfo) ||
    (isComunidad &&
      negativeOption.some((opt) =>
        isComunidad.label?.toLowerCase().includes(opt.toLowerCase())
      ));

  if (error) {
    console.error('Error al cargar el cuestionario:', error);
    return <div>Error al cargar el cuestionario</div>;
  }

  return (
    <div className="preguntas">
      <hr />
      <h2 className="text-xl font-bold">{data?.cuestionario.nombre_form}</h2>
      {data?.cuestionario.descripcion && (
        <MarkdownRenderer markdown={data.cuestionario.descripcion} />
      )}

      {preguntaComunidad && (
        <div className="my-4">
          <label
            className={`form-label ${
              preguntaComunidad.obligatoria ? 'required' : ''
            }`}
          >
            {preguntaComunidad.pregunta}
          </label>
          <RadioOptionGroup
            name="comunidad"
            options={preguntaComunidad.opciones.map((op) => ({
              label: op.opcion.opcion,
              value: op.id_opcion,
            }))}
            selectedValue={isComunidad?.value}
            onChange={(opt) => {
              console.log('Opción comunidad seleccionada:', opt);
              setIsComunidad(opt);
              actualizarRespuesta(
                preguntaComunidad.id_pregunta.toString(),
                String(opt.value)
              );
            }}
          />
        </div>
      )}

      {isComunidad &&
        confirmativeOption.some((opt) =>
          isComunidad.label?.toLowerCase().includes(opt.toLowerCase())
        ) &&
        preguntaCuenta && (
          <div className="my-4">
            <label
              className={`form-label ${
                preguntaCuenta.obligatoria ? 'required' : ''
              }`}
            >
              {preguntaCuenta.pregunta}
            </label>
            <SimpleInput
              type="text"
              name="cuenta"
              placeholder="Ingrese su cuenta"
              maxLength={10}
              value={respuestas[preguntaCuenta.id_pregunta] || ''}
              onChange={(e) =>
                setRespuestas((prev) => ({
                  ...prev,
                  [preguntaCuenta.id_pregunta]: e.target.value,
                }))
              }
            />
          </div>
        )}

      {mostrarFormularioRestante &&
        data?.cuestionario.secciones.map((seccion, i) => (
          <div key={i}>
            {seccion.preguntas.map((pregunta) => {
              // Evitar renderizar las preguntas ya manejadas
              if (
                pregunta.pregunta.id_pregunta ===
                  preguntaComunidad?.id_pregunta ||
                pregunta.pregunta.id_pregunta === preguntaCuenta?.id_pregunta
              )
                return null;

              if (
                pregunta.pregunta.tipo_pregunta.tipo_pregunta ===
                'Abierta (Respuesta corta)'
              ) {
                return (
                  <PrefetchAbiertaCorta
                    key={pregunta.pregunta.id_pregunta}
                    obligatorio={pregunta.pregunta.obligatoria}
                    idPregunta={pregunta.pregunta.id_pregunta}
                    enunciado={pregunta.pregunta.pregunta}
                    validacion={pregunta.pregunta.validacion}
                    respuestas={respuestas}
                    cuentaInfo={cuentaInfo}
                    isComunidad={isComunidad?.label}
                    onChange={actualizarRespuesta}
                    preguntaComunidad={preguntaComunidad?.validacion ?? ''}
                  />
                );
              }

              if (
                pregunta.pregunta.tipo_pregunta.tipo_pregunta ===
                'Abierta (Parrafo)'
              ) {
                return (
                  <div key={pregunta.pregunta.id_pregunta} className="my-4">
                    <label
                      className={`form-label ${
                        pregunta.pregunta.obligatoria ? 'required' : ''
                      }`}
                    >
                      {pregunta.pregunta.pregunta}
                    </label>
                    <SimpleInput
                      type="textarea"
                      name={`respuesta_${pregunta.pregunta.id_pregunta}`}
                      placeholder="Ingrese una respuesta"
                      value={respuestas[pregunta.pregunta.id_pregunta] || ''}
                      onChange={(e) =>
                        setRespuestas((prev) => ({
                          ...prev,
                          [pregunta.pregunta.id_pregunta]: e.target.value,
                        }))
                      }
                    />
                  </div>
                );
              }

              if (pregunta.pregunta.tipo_pregunta.tipo_pregunta === 'Cerrada') {
                const opciones: RadioOption<number>[] =
                  pregunta.pregunta.opciones.map((op) => ({
                    label: op.opcion.opcion,
                    value: op.id_opcion,
                  }));
                let respuestaActual =
                  respuestas[`${pregunta.pregunta.id_pregunta}`];

                if (
                  confirmativeOption.includes(isComunidad?.label) &&
                  cuentaInfo &&
                  respuestaActual === undefined // solo si no ha respondido
                ) {
                  if (pregunta.pregunta.validacion === 'genero') {
                    const generoTexto =
                      cuentaInfo.genero === 'M' ? 'Masculino' : 'Femenino';

                    const opcionGenero = pregunta.pregunta.opciones.find(
                      (op) =>
                        op.opcion.opcion.toLowerCase() ===
                        generoTexto.toLowerCase()
                    );
                    if (opcionGenero) {
                      respuestaActual = String(opcionGenero.id_opcion);
                    }
                  }
                }

                return (
                  <div key={pregunta.pregunta.id_pregunta}>
                    <label
                      className={`form-label ${
                        pregunta.pregunta.obligatoria ? 'required' : ''
                      }`}
                    >
                      {pregunta.pregunta.pregunta}
                    </label>
                    <RadioOptionGroup
                      name={`pregunta_${pregunta.pregunta.id_pregunta}`}
                      options={opciones}
                      selectedValue={
                        respuestaActual ? Number(respuestaActual) : undefined
                      }
                      onChange={(opt) => {
                        actualizarRespuesta(
                          `${pregunta.pregunta.id_pregunta}`,
                          String(opt.value)
                        );
                      }}
                    />
                  </div>
                );
              }

              return (
                <div key={pregunta.pregunta.id_pregunta} className="my-4">
                  <label
                    className={`form-label ${
                      pregunta.pregunta.obligatoria ? 'required' : ''
                    }`}
                  >
                    {pregunta.pregunta.pregunta}
                  </label>
                </div>
              );
            })}
          </div>
        ))}

      <Button
        className="btn btn-primary"
        onClick={handleOnSubmit}
        disabled={!mostrarFormularioRestante || isSending}
      >
        {isSending ? 'Enviando...' : 'Enviar Formulario'}
      </Button>
    </div>
  );
}
