import { client } from "@/utils/api";
import { unwrap } from "@/utils/endpoint";
import { URL_CONSTANTS } from "@/constants/URLS";
import type { ApiResponse } from "@/types/apiResponse";
import type { ProfileResponse, UpdateProfilePayload } from "@/types/profile";
import { isAxiosError } from "axios";

export type ProfileTypeValue =
  | "importer"
  | "exporter"
  | "freight_forwarder"
  | "dj_freight_forwarder"
  | "transporter";

export type CompanyNationality = "ethiopian" | "foreign";

export interface LicenseFile {
  name: string;
  url: string;
  size: number;
  mimeType?: string;
}

export interface ExternalProfileResponse {
  id: string;
  userId: string;
  companyId: string;
  firstName: string;
  lastName: string;
  email: string;
  phone: string | null;
  nationalId: string | null;
  jobTitle: string | null;
  isPrimaryContact: boolean;
  /** The active operational mode (importer/exporter/forwarder). */
  activeProfileType: ProfileTypeValue | null;
  /** Id of the company_profile matching activeProfileType (server-resolved). */
  activeCompanyProfileId: string | null;
  onboardingStep: string | null;
  onboardingCompleted: boolean;
  createdAt: string;
  updatedAt: string;
}

export interface CompanyResponse {
  id: string;
  name: string;
  type: string;
  status: string;
  nationality: CompanyNationality | null;
  tin: string;
  vatNumber: string | null;
  businessLicense: string | null;
  fanNumber: string | null;
  country: string;
  address: string | null;
  phone: string | null;
  email: string | null;
  website: string | null;
  attributes: Record<string, any> | null;
  companyProfiles?: CompanyProfileResponse[];
  createdAt: string;
  updatedAt: string;
}

export interface CompanyProfileResponse {
  id: string;
  type: string;
  reference: string;
  status: string;
  /** @deprecated Superseded by licenseFiles (file model). */
  businessLicense: string | null;
  /** Business-license documents uploaded for this profile. */
  licenseFiles: LicenseFile[];
  attributes: Record<string, any> | null;
  createdAt: string;
  updatedAt: string;
}

export interface CompanyInfoResponse {
  profile: ExternalProfileResponse;
  company: CompanyResponse;
}

export interface CompanyProfileInput {
  type: "importer" | "exporter" | "freight_forwarder" | "dj_freight_forwarder" | "transporter";
  businessLicense?: string;
}

export interface CreateCompanyPayload {
  companyType?: string;
  nationality?: CompanyNationality;
  companyName: string;
  companyEmail?: string;
  companyPhone?: string;
  companyLocation?: string;
  companyAddress?: string;
  tin?: string;
  vatNumber?: string;
  fanNumber?: string;
  jobTitle?: string;
  isPrimaryContact?: boolean;
  attributes?: Record<string, any>;
  companyProfiles?: CompanyProfileInput[];
}

export interface FreightVolumePoint {
  month: string;
  tonnes: number;
}

export interface DashboardSummary {
  deliveredCount: number;
  completionRate: number;
  spendYtd: number;
  spendCurrency: string;
  spendYtdChangePct: number;
  freightVolume: {
    totalTonnes: number;
    totalValue: number;
    currency: string;
    ytdChangePct: number;
    monthly: FreightVolumePoint[];
  };
}

export const companiesService = {
  getInfo: async (): Promise<CompanyInfoResponse | null> => {
    try {
      const response = await client.get<ApiResponse<CompanyInfoResponse>>(
        URL_CONSTANTS.COMPANIES_API.GET_INFO,
      );
      return unwrap(response.data);
    } catch (e) {
      if (isAxiosError(e) && e.response?.status === 404) {
        return null;
      }
      throw e;
    }
  },

  create: async (payload: CreateCompanyPayload): Promise<CompanyInfoResponse> => {
    const response = await client.post<ApiResponse<CompanyInfoResponse>>(
      URL_CONSTANTS.COMPANIES_API.CREATE,
      payload,
    );
    return unwrap(response.data);
  },

  getProfile: async (): Promise<ProfileResponse> => {
    const response = await client.get<ApiResponse<ProfileResponse>>(
      URL_CONSTANTS.COMPANIES_API.PROFILE,
    );
    return unwrap(response.data);
  },

  updateProfile: async (payload: UpdateProfilePayload): Promise<ProfileResponse> => {
    const response = await client.patch<ApiResponse<ProfileResponse>>(
      URL_CONSTANTS.COMPANIES_API.PROFILE,
      payload,
    );
    return unwrap(response.data);
  },

  getDashboard: async (
    companyProfileId?: string,
  ): Promise<DashboardSummary> => {
    const response = await client.get<ApiResponse<DashboardSummary>>(
      URL_CONSTANTS.COMPANIES_API.DASHBOARD,
      { params: companyProfileId ? { companyProfileId } : undefined },
    );
    return unwrap(response.data);
  },

  addCompanyProfiles: async (payload: {
    types: string[];
  }): Promise<CompanyProfileResponse[]> => {
    const response = await client.post<ApiResponse<CompanyProfileResponse[]>>(
      URL_CONSTANTS.COMPANIES_API.COMPANY_PROFILES,
      payload,
    );
    return unwrap(response.data);
  },

  /** Create a single operational profile and make it the active mode. */
  createCompanyProfile: async (payload: {
    type: ProfileTypeValue;
    businessLicense?: string;
  }): Promise<CompanyProfileResponse> => {
    const response = await client.post<ApiResponse<CompanyProfileResponse>>(
      URL_CONSTANTS.COMPANIES_API.COMPANY_PROFILE,
      payload,
    );
    return unwrap(response.data);
  },

  /** Begin onboarding — create the draft company + profile + role(s) up front. */
  startOnboarding: async (payload: {
    companyType: string;
    roles: ProfileTypeValue[];
    nationality?: CompanyNationality;
  }): Promise<CompanyInfoResponse> => {
    const response = await client.post<ApiResponse<CompanyInfoResponse>>(
      URL_CONSTANTS.COMPANIES_API.ONBOARDING_START,
      payload,
    );
    return unwrap(response.data);
  },

  /** Switch the active operational mode (target profile must already exist). */
  setActiveMode: async (payload: {
    type: ProfileTypeValue;
  }): Promise<CompanyInfoResponse> => {
    const response = await client.patch<ApiResponse<CompanyInfoResponse>>(
      URL_CONSTANTS.COMPANIES_API.ACTIVE_MODE,
      payload,
    );
    return unwrap(response.data);
  },

  setOnboardingStep: async (payload: { step: string }): Promise<void> => {
    await client.patch(URL_CONSTANTS.COMPANIES_API.ONBOARDING_STEP, payload);
  },

  completeOnboarding: async (): Promise<CompanyInfoResponse> => {
    const response = await client.post<ApiResponse<CompanyInfoResponse>>(
      URL_CONSTANTS.COMPANIES_API.ONBOARDING_COMPLETE,
    );
    return unwrap(response.data);
  },

  uploadDocuments: async (
    companyId: string,
    files: Record<string, File | File[] | null>,
  ): Promise<void> => {
    const formData = new FormData();
    for (const [fieldName, fileOrFiles] of Object.entries(files)) {
      if (!fileOrFiles) continue;
      if (Array.isArray(fileOrFiles)) {
        for (const f of fileOrFiles) {
          formData.append(fieldName, f);
        }
      } else {
        formData.append(fieldName, fileOrFiles);
      }
    }
    await client.post(URL_CONSTANTS.COMPANIES_API.DOCUMENTS(companyId), formData);
  },

  /** Upload business-license document(s) for a company profile (multi-file). */
  uploadProfileLicense: async (
    profileId: string,
    files: File[],
    code = "business_license",
  ): Promise<LicenseFile[]> => {
    const formData = new FormData();
    for (const f of files) formData.append(code, f);
    const response = await client.post<ApiResponse<LicenseFile[]>>(
      URL_CONSTANTS.COMPANIES_API.PROFILE_LICENSE(profileId),
      formData,
    );
    return unwrap(response.data);
  },

  /** List business-license document(s) already uploaded for a company profile. */
  getProfileLicense: async (profileId: string): Promise<LicenseFile[]> => {
    const response = await client.get<ApiResponse<LicenseFile[]>>(
      URL_CONSTANTS.COMPANIES_API.PROFILE_LICENSE(profileId),
    );
    return unwrap(response.data);
  },

  /** Fetch company registration data from eTrade by TIN. */
  fetchETradeInfo: async (payload: { tin: string }): Promise<any> => {
    const response = await client.post<ApiResponse<any>>(
      URL_CONSTANTS.COMPANIES_API.FETCH_ETRADE_INFO,
      payload,
    );
    return unwrap(response.data);
  },
};
