"use client";

import { useTranslations } from "next-intl";
import { Fragment, createContext, ReactNode, useContext, useState } from "react";
import { SharedProvider } from "../../../contexts";
import { JsonApiHydratedDataInterface, Modules, rehydrate } from "../../../core";
import { usePageUrlGenerator } from "../../../hooks";
import { BreadcrumbItemData } from "../../../interfaces";
import { Action } from "../../../permissions";
import { getRoleId } from "../../../roles";
import { UserInterface } from "../../user";
import { useCurrentUserContext } from "../../user/contexts";
import { CompanyDeleter, CompanyEditor } from "../components";
import { CompanyInterface } from "../data";

interface CompanyContextType {
  company: CompanyInterface | undefined;
  setCompany: (value: CompanyInterface | undefined) => void;
}

const CompanyContext = createContext<CompanyContextType | undefined>(undefined);

type CompanyProviderProps = {
  children: ReactNode;
  dehydratedCompany?: JsonApiHydratedDataInterface;
  configurationEditorSlot?: ReactNode;
};

const defaultContextValue: CompanyContextType = {
  company: undefined,
  setCompany: () => {},
};

export const CompanyProvider = ({ children, dehydratedCompany, configurationEditorSlot }: CompanyProviderProps) => {
  const generateUrl = usePageUrlGenerator();
  const t = useTranslations();
  const { hasPermissionToModule, hasRole } = useCurrentUserContext<UserInterface>();

  const [company, setCompany] = useState<CompanyInterface | undefined>(
    dehydratedCompany ? rehydrate<CompanyInterface>(Modules.Company, dehydratedCompany) : undefined,
  );

  const breadcrumb = () => {
    const response: BreadcrumbItemData[] = [];

    // The list root always comes first, exactly as UserProvider does it —
    // without it the company list rendered a breadcrumb of just "Home", while
    // every sibling administration page showed its own name.
    //
    // Linked ONLY when it is not the current page: the Company module's
    // `pageUrl` is /companies, which the administration tree does not route, so
    // a link from the list itself would land on a 404.
    response.push({
      name: t(`entities.companies`, { count: 2 }),
      ...(company ? { href: generateUrl({ page: Modules.Company }) } : {}),
    });

    if (company)
      response.push({
        name: company.name,
        href: generateUrl({ page: Modules.Company, id: company.id }),
      });

    return response;
  };

  const title = () => {
    const response: any = {
      type: t(`entities.companies`, { count: company ? 1 : 2 }),
    };

    if (company) response.element = company.name;

    const functions: ReactNode[] = [];

    if (
      company &&
      (hasRole(getRoleId().Administrator) || hasRole(getRoleId().CompanyAdministrator)) &&
      hasPermissionToModule({ module: Modules.Company, action: Action.Delete })
    )
      functions.push(<CompanyDeleter key="companyDeleter" company={company} />);

    if (
      hasRole(getRoleId().Administrator) ||
      hasPermissionToModule({ module: Modules.Company, action: Action.Update })
    ) {
      if (company && configurationEditorSlot)
        functions.push(<Fragment key="configurationEditorSlot">{configurationEditorSlot}</Fragment>);
      functions.push(<CompanyEditor key="companyEditor" company={company} propagateChanges={setCompany} />);
    }

    if (functions.length > 0) response.functions = functions;

    return response;
  };

  return (
    <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>
      <CompanyContext.Provider
        value={{
          company: company,
          setCompany: setCompany,
        }}
      >
        {children}
      </CompanyContext.Provider>
    </SharedProvider>
  );
};

export const useCompanyContext = (): CompanyContextType => {
  return useContext(CompanyContext) ?? defaultContextValue;
};
