import type { Transaction } from "../generated/kysely-tailordb";
import {
  CompanyNotFoundError,
  FiscalYearNotFoundError,
  CostObjectNotFoundError,
  PlanVersionNotFoundError,
  InvalidNameError,
  BudgetHolderRequiredError,
} from "../lib/errors.generated";
import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/module";

export interface CreateBudgetInput {
  companyId: string;
  name: string;
  description?: string | null;
  budgetHolderId: string | null;
  fiscalYearId: string;
  costObjectType: "CostCenter" | "ProfitCenter" | "InternalOrder";
  costObjectId: string;
  planVersionId: string;
}

export async function run(db: Transaction, input: CreateBudgetInput, ctx: CommandContext) {
  // Validate company exists and is ACTIVE
  const company = await db
    .selectFrom("Company" as never)
    .where("id" as never, "=", input.companyId as never)
    .selectAll()
    .executeTakeFirst();

  if (!company || (company as Record<string, unknown>).status !== "ACTIVE") {
    return err(new CompanyNotFoundError(input.companyId));
  }

  // Validate fiscal year exists
  const fiscalYear = await db
    .selectFrom("FiscalYear" as never)
    .where("id" as never, "=", input.fiscalYearId as never)
    .selectAll()
    .executeTakeFirst();

  if (!fiscalYear) {
    return err(new FiscalYearNotFoundError(input.fiscalYearId));
  }

  // Validate cost object exists (polymorphic lookup)
  const costObject = await db
    .selectFrom(input.costObjectType as never)
    .where("id" as never, "=", input.costObjectId as never)
    .selectAll()
    .executeTakeFirst();

  if (!costObject) {
    return err(new CostObjectNotFoundError(input.costObjectId));
  }

  // Validate plan version exists
  const planVersion = await db
    .selectFrom("PlanVersion")
    .where("id", "=", input.planVersionId)
    .selectAll()
    .executeTakeFirst();

  if (!planVersion) {
    return err(new PlanVersionNotFoundError(input.planVersionId));
  }

  // Validate name is non-empty
  if (!input.name || input.name.trim() === "") {
    return err(new InvalidNameError(input.companyId));
  }

  // Validate budget holder is provided
  if (!input.budgetHolderId) {
    return err(new BudgetHolderRequiredError(input.companyId));
  }

  // Create budget in DRAFT status
  const budget = await db
    .insertInto("Budget")
    .values({
      companyId: input.companyId,
      name: input.name,
      description: input.description ?? null,
      budgetHolderId: input.budgetHolderId,
      fiscalYearId: input.fiscalYearId,
      costObjectType: input.costObjectType,
      costObjectId: input.costObjectId,
      planVersionId: input.planVersionId,
      totalAmount: 0,
      status: "DRAFT",
      createdByUserId: ctx.actorId,
      createdAt: new Date(),
      updatedAt: null,
    })
    .returningAll()
    .executeTakeFirst();

  return ok({ budget: budget! });
}
