import {
  CWActivity,
  CWActivityCustomField,
  CWPatchOperation,
  CWCreateActivity,
} from "../modules/cw-utils/activities/activity.types";
import { activityCw } from "../modules/cw-utils/activities/activities";

/**
 * Activity Controller
 *
 * Domain model class that encapsulates a ConnectWise Activity entity.
 * Activities are not persisted locally — all data is sourced directly
 * from the ConnectWise API.
 */
export class ActivityController {
  public readonly cwActivityId: number;
  public name: string;
  public notes: string | null;

  public typeName: string | null;
  public typeCwId: number | null;
  public statusName: string | null;
  public statusCwId: number | null;

  public companyCwId: number | null;
  public companyName: string | null;
  public companyIdentifier: string | null;
  public contactCwId: number | null;
  public contactName: string | null;

  public phoneNumber: string | null;
  public email: string | null;

  public opportunityCwId: number | null;
  public opportunityName: string | null;
  public ticketCwId: number | null;
  public ticketName: string | null;
  public agreementCwId: number | null;
  public agreementName: string | null;
  public campaignCwId: number | null;
  public campaignName: string | null;

  public assignToCwId: number | null;
  public assignToName: string | null;
  public assignToIdentifier: string | null;

  public scheduleStatusCwId: number | null;
  public scheduleStatusName: string | null;
  public reminderCwId: number | null;
  public reminderName: string | null;
  public whereCwId: number | null;
  public whereName: string | null;

  public dateStart: Date | null;
  public dateEnd: Date | null;
  public notifyFlag: boolean;

  public currencyCwId: number | null;
  public currencyName: string | null;

  public mobileGuid: string | null;
  public customFields: CWActivityCustomField[];

  public cwLastUpdated: Date | null;
  public cwDateEntered: Date | null;
  public cwEnteredBy: string | null;
  public cwUpdatedBy: string | null;

  constructor(data: CWActivity) {
    this.cwActivityId = data.id;
    this.name = data.name;
    this.notes = data.notes ?? null;

    this.typeName = data.type?.name ?? null;
    this.typeCwId = data.type?.id ?? null;
    this.statusName = data.status?.name ?? null;
    this.statusCwId = data.status?.id ?? null;

    this.companyCwId = data.company?.id ?? null;
    this.companyName = data.company?.name ?? null;
    this.companyIdentifier = data.company?.identifier ?? null;
    this.contactCwId = data.contact?.id ?? null;
    this.contactName = data.contact?.name ?? null;

    this.phoneNumber = data.phoneNumber ?? null;
    this.email = data.email ?? null;

    this.opportunityCwId = data.opportunity?.id ?? null;
    this.opportunityName = data.opportunity?.name ?? null;
    this.ticketCwId = data.ticket?.id ?? null;
    this.ticketName = data.ticket?.name ?? null;
    this.agreementCwId = data.agreement?.id ?? null;
    this.agreementName = data.agreement?.name ?? null;
    this.campaignCwId = data.campaign?.id ?? null;
    this.campaignName = data.campaign?.name ?? null;

    this.assignToCwId = data.assignTo?.id ?? null;
    this.assignToName = data.assignTo?.name ?? null;
    this.assignToIdentifier = data.assignTo?.identifier ?? null;

    this.scheduleStatusCwId = data.scheduleStatus?.id ?? null;
    this.scheduleStatusName = data.scheduleStatus?.name ?? null;
    this.reminderCwId = data.reminder?.id ?? null;
    this.reminderName = data.reminder?.name ?? null;
    this.whereCwId = data.where?.id ?? null;
    this.whereName = data.where?.name ?? null;

    this.dateStart = data.dateStart ? new Date(data.dateStart) : null;
    this.dateEnd = data.dateEnd ? new Date(data.dateEnd) : null;
    this.notifyFlag = data.notifyFlag ?? false;

    this.currencyCwId = data.currency?.id ?? null;
    this.currencyName = data.currency?.name ?? null;

    this.mobileGuid = data.mobileGuid ?? null;
    this.customFields = data.customFields ?? [];

    this.cwLastUpdated = data._info?.lastUpdated
      ? new Date(data._info.lastUpdated)
      : null;
    this.cwDateEntered = data._info?.dateEntered
      ? new Date(data._info.dateEntered)
      : null;
    this.cwEnteredBy = data._info?.enteredBy ?? null;
    this.cwUpdatedBy = data._info?.updatedBy ?? null;
  }

  /**
   * Update in ConnectWise
   *
   * Applies JSON Patch operations to this activity in ConnectWise
   * and returns a new controller with the updated data.
   */
  public async update(
    operations: CWPatchOperation[],
  ): Promise<ActivityController> {
    const updated = await activityCw.update(this.cwActivityId, operations);
    return new ActivityController(updated);
  }

  /**
   * Delete from ConnectWise
   *
   * Deletes this activity in ConnectWise.
   */
  public async delete(): Promise<void> {
    await activityCw.delete(this.cwActivityId);
  }

  /**
   * Create Activity (static factory)
   *
   * Creates a new activity in ConnectWise and returns a controller instance.
   */
  public static async create(
    data: CWCreateActivity,
  ): Promise<ActivityController> {
    const created = await activityCw.create(data);
    return new ActivityController(created);
  }

  /**
   * To JSON
   *
   * Serializes the activity into a safe, API-friendly object.
   */
  public toJson(): Record<string, any> {
    return {
      cwActivityId: this.cwActivityId,
      name: this.name,
      notes: this.notes,
      type: this.typeCwId ? { id: this.typeCwId, name: this.typeName } : null,
      status: this.statusCwId
        ? { id: this.statusCwId, name: this.statusName }
        : null,
      company: this.companyCwId
        ? {
            id: this.companyCwId,
            identifier: this.companyIdentifier,
            name: this.companyName,
          }
        : null,
      contact: this.contactCwId
        ? { id: this.contactCwId, name: this.contactName }
        : null,
      phoneNumber: this.phoneNumber,
      email: this.email,
      opportunity: this.opportunityCwId
        ? { id: this.opportunityCwId, name: this.opportunityName }
        : null,
      ticket: this.ticketCwId
        ? { id: this.ticketCwId, name: this.ticketName }
        : null,
      agreement: this.agreementCwId
        ? { id: this.agreementCwId, name: this.agreementName }
        : null,
      campaign: this.campaignCwId
        ? { id: this.campaignCwId, name: this.campaignName }
        : null,
      assignTo: this.assignToCwId
        ? {
            id: this.assignToCwId,
            identifier: this.assignToIdentifier,
            name: this.assignToName,
          }
        : null,
      scheduleStatus: this.scheduleStatusCwId
        ? { id: this.scheduleStatusCwId, name: this.scheduleStatusName }
        : null,
      reminder: this.reminderCwId
        ? { id: this.reminderCwId, name: this.reminderName }
        : null,
      where: this.whereCwId
        ? { id: this.whereCwId, name: this.whereName }
        : null,
      dateStart: this.dateStart,
      dateEnd: this.dateEnd,
      notifyFlag: this.notifyFlag,
      currency: this.currencyCwId
        ? { id: this.currencyCwId, name: this.currencyName }
        : null,
      mobileGuid: this.mobileGuid,
      customFields: this.customFields,
      cwLastUpdated: this.cwLastUpdated,
      cwDateEntered: this.cwDateEntered,
      cwEnteredBy: this.cwEnteredBy,
      cwUpdatedBy: this.cwUpdatedBy,
    };
  }
}
