'use client';

import { useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import * as Yup from 'yup';
import { RootState } from '@/store';
import { setDeviceData, setProgramNumber, setSaving, setSaveError } from '@/store/slices/installation-slice';
import { InstallationRepository } from '@/repositories/teltoinstall/_index';
import { apiErrorMessage, extractValidationErrors } from '@/utils/teltoinstall/_index';
import { Device } from '@/models/teltoinstall/_index';

export interface SaveDeviceResult {
  ok: boolean;
  /** Erreurs de validation serveur (422) indexées par nom de champ Formik. */
  fieldErrors?: Record<string, string>;
}

export function useDeviceStep() {
  const { t } = useTranslation();
  const dispatch = useDispatch();
  const { device, installationId, program_number } = useSelector(
    (state: RootState) => state.installation
  );

  const validationSchema = Yup.object({
    stock_origin: Yup.string().required(t('errors.stockOriginRequired')),
    telematics_box_id: Yup.string().required(t('errors.telematicsBoxRequired')),
    imei: Yup.string()
      .required(t('errors.imeiRequired'))
      .length(15, t('errors.imeiLength'))
      .matches(/^\d+$/, t('errors.imeiDigits')),
    has_can_module: Yup.boolean(),
    can_module_type_id: Yup.number().when('has_can_module', {
      is: true,
      then: (s) => s.required(t('errors.canModuleTypeRequired')),
    }),
    // Numéro de programme obligatoire pour un boîtier à bus CAN (champ masqué sinon).
    program_number: Yup.string().when('has_can_module', {
      is: true,
      then: (s) => s.required(t('errors.programNumberRequired')),
    }),
    sim_card: Yup.object({
      iccid: Yup.string().optional(),
    }).optional(),
    accessory_ids: Yup.array().optional(),
  });

  async function saveDevice(
    values: Partial<Device> & { accessory_ids?: number[]; program_number?: string }
  ): Promise<SaveDeviceResult> {
    // program_number est un champ de l'installation (pas du boîtier) : on l'isole
    // de la charge utile `device` et on le persiste à la racine de la pose.
    const { program_number: programNumber, ...deviceValues } = values;
    dispatch(setDeviceData(deviceValues));
    dispatch(setProgramNumber(programNumber ?? ''));
    if (!installationId) return { ok: false };
    dispatch(setSaving(true));
    try {
      const { accessory_ids, ...deviceData } = deviceValues;
      await InstallationRepository.update(installationId, {
        device: deviceData as Device,
        program_number: programNumber ?? '',
      });
      if (accessory_ids !== undefined) {
        await InstallationRepository.update(installationId, { accessories: accessory_ids });
      }
      return { ok: true };
    } catch (err) {
      // Erreur de validation serveur (ex. IMEI déjà utilisé) : on la remonte au
      // formulaire pour l'afficher en ligne sur le champ concerné.
      const fieldErrors = extractValidationErrors(err);
      if (fieldErrors) return { ok: false, fieldErrors };
      // Erreur non-422 (métier/réseau) : on remonte le message backend au toast.
      dispatch(setSaveError(apiErrorMessage(err, t('wizard.saveError'))));
      return { ok: false };
    } finally {
      dispatch(setSaving(false));
    }
  }

  return { device, program_number, validationSchema, saveDevice };
}
