/* eslint-disable @typescript-eslint/no-explicit-any */
import { BirthdayRangeCreator, BirthdayRangeDay } from '@/types/Birthday';
import { CreatorBirthdayInfo, CreatorData, CreatorListData } from '@/types/Creator';

import { javaPost } from './apiClient';

interface CreatorListRequestBody {
  firstResult: number;
  maxResults: number;
  metaIdList: number[] | null;
  onlyWithData: boolean;
  withCoord: boolean | null;
  queryString: string | null;
}

const defaultCreatorListRequestBody: CreatorListRequestBody = {
  firstResult: 0,
  maxResults: 1000,
  metaIdList: null,
  onlyWithData: false,
  withCoord: null,
  queryString: null,
};

export async function getCreatorList({
  body = {},
  options = {},
}: {
  body?: Partial<CreatorListRequestBody>;
  options?: any;
} = {}): Promise<CreatorListData[]> {
  try {
    const res = await javaPost(
      'personControl/getList',
      { ...defaultCreatorListRequestBody, ...body },
      options
    );

    return res || [];
  } catch (error) {
    console.error('Failed to get creator list:', error);
    return []; // fallback
  }
}

export async function getCreatorData(id: string): Promise<CreatorData | null> {
  return javaPost('personControl/getDataNew', {
    personId: null,
    personIdentifier: id,
  }).then((res) => {
    if (!res || !res.nev || !res.alkotoAzonosito) return null;
    return res;
  });
}

export async function getCreatorLifeEvents(id: any) {
  return javaPost('personControl/getLifeEvent', {
    personId: null,
    personIdentifier: id,
  }).then((data) => {
    if (!data) return [];
    // only life events
    return data;
  });
}

export async function getCreatorNews(id: any) {
  return javaPost('personControl/getMmaNewsEvent', {
    personId: null,
    personIdentifier: id,
  }).then((data) => {
    if (!data) return [];
    // only news
    return data;
  });
}

export async function getCreatorCV(personId: string | number) {
  return javaPost('personControl/getCV', {
    personId,
  });
}

type CreatorBirthdayDate = {
  year: number;
  month: number;
  day: number;
};

const getBirthdayDateParts = (
  dateOrParts?: Date | Partial<CreatorBirthdayDate>
): CreatorBirthdayDate => {
  if (dateOrParts instanceof Date) {
    return {
      year: dateOrParts.getFullYear(),
      month: dateOrParts.getMonth() + 1,
      day: dateOrParts.getDate(),
    };
  }

  const now = new Date();

  return {
    year: dateOrParts?.year ?? now.getFullYear(),
    month: dateOrParts?.month ?? now.getMonth() + 1,
    day: dateOrParts?.day ?? now.getDate(),
  };
};

export async function getCreatorBirthdays(
  dateOrParts?: Date | Partial<CreatorBirthdayDate>,
  options?: { locale?: string; throwOnError?: boolean }
): Promise<CreatorBirthdayInfo[] | null> {
  const { year, month, day } = getBirthdayDateParts(dateOrParts);

  try {
    const response = await javaPost(
      'personControl/getBirthdayInfo',
      {
        year: String(year),
        month: String(month),
        day: String(day),
      },
      options?.locale ? { headers: { 'X-Language': options.locale } } : {}
    );

    if (!Array.isArray(response) || response.length === 0) {
      return null;
    }

    const birthdays = response
      .filter((item): item is { imgKey?: unknown; orderKey?: unknown; text?: unknown } =>
        Boolean(item && typeof item === 'object')
      )
      .map((item) => ({
        imgKey: typeof item.imgKey === 'string' && item.imgKey.length > 0 ? item.imgKey : null,
        orderKey:
          typeof item.orderKey === 'string' && item.orderKey.length > 0 ? item.orderKey : null,
        text: typeof item.text === 'string' ? item.text : '',
      }))
      .filter((item) => item.text.length > 0);

    return birthdays.length > 0 ? birthdays : null;
  } catch (error) {
    console.error('Failed to get creator birthdays:', error);
    if (options?.throwOnError) {
      throw error;
    }
    return null;
  }
}

export const getBirthdays = getCreatorBirthdays;

const ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;

const toNullableString = (value: unknown) =>
  typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;

const toNullableNumber = (value: unknown) => {
  if (typeof value === 'number' && Number.isFinite(value)) return value;
  if (typeof value === 'string') {
    const parsed = Number(value);
    if (Number.isFinite(parsed)) return parsed;
  }
  return null;
};

const toBoolean = (value: unknown) => value === true;

const isValidDateIso = (value: string) => ISO_DATE_PATTERN.test(value);

const normalizeBirthdayRangeCreator = (item: unknown): BirthdayRangeCreator | null => {
  if (!item || typeof item !== 'object') return null;
  const creator = item as Record<string, unknown>;

  const id = toNullableNumber(creator.id);
  const alkotoAzonosito = toNullableString(creator.alkotoAzonosito);
  const nev = toNullableString(creator.nev);

  if (id === null || !alkotoAzonosito || !nev) {
    return null;
  }

  return {
    id,
    alkotoAzonosito,
    nev,
    szakma: toNullableString(creator.szakma) ?? '',
    imgKey: toNullableString(creator.imgKey),
    elhunyt: toBoolean(creator.elhunyt),
    szuletesiEv: toNullableNumber(creator.szuletesiEv),
    szuletesiHonap: toNullableNumber(creator.szuletesiHonap),
    szuletesiNap: toNullableNumber(creator.szuletesiNap),
    szuletesiHely: toNullableString(creator.szuletesiHely),
    evfordulo: toNullableNumber(creator.evfordulo),
  };
};

const normalizeBirthdayRangeDay = (item: unknown): BirthdayRangeDay | null => {
  if (!item || typeof item !== 'object') return null;
  const day = item as Record<string, unknown>;
  const dateIso = toNullableString(day.dateIso);

  if (!dateIso || !isValidDateIso(dateIso)) {
    return null;
  }

  const rawCreators = Array.isArray(day.alkotok) ? day.alkotok : [];
  const alkotok = rawCreators
    .map((creator) => normalizeBirthdayRangeCreator(creator))
    .filter((creator): creator is BirthdayRangeCreator => Boolean(creator));

  return {
    dateIso,
    alkotok,
  };
};

export async function getCreatorBirthdaysByRange(
  params: { fromDate: string; toDate: string },
  options: { locale?: string; throwOnError?: boolean } = {}
): Promise<BirthdayRangeDay[]> {
  const { fromDate, toDate } = params;

  try {
    const response = await javaPost(
      `personControl/getBirthdayInfo?fromDate=${encodeURIComponent(fromDate)}&toDate=${encodeURIComponent(toDate)}`,
      {},
      options.locale ? { headers: { 'X-Language': options.locale } } : {}
    );

    if (!Array.isArray(response) || response.length === 0) {
      return [];
    }

    return response
      .map((day) => normalizeBirthdayRangeDay(day))
      .filter((day): day is BirthdayRangeDay => Boolean(day));
  } catch (error) {
    console.error('Failed to get creator birthdays by range:', error);
    if (options.throwOnError) {
      throw error;
    }
    return [];
  }
}
