import { apiClient, getDataOrDefault } from "@/core/api";
import {
  simInfoSchema,
  simAvailablePlanArraySchema,
  simCancellationPreviewSchema,
  simDomesticCallHistoryResponseSchema,
  simInternationalCallHistoryResponseSchema,
  simSmsHistoryResponseSchema,
  simHistoryAvailableMonthsSchema,
  type SimAvailablePlan,
  type SimInfo,
  type SimCancelFullRequest,
  type SimChangePlanFullRequest,
  type SimCancellationPreview,
  type SimDomesticCallHistoryResponse,
  type SimInternationalCallHistoryResponse,
  type SimSmsHistoryResponse,
  type SimReissueFullRequest,
  SimTopUpRequest,
  SimPlanChangeRequest,
  SimCancelRequest,
} from "@customer-portal/domain/sim";
import type { SimPlanChangeResult } from "@customer-portal/domain/subscriptions";

// Types imported from domain - no duplication
// Domain schemas provide validation rules:
// - SimTopUpRequest: quotaMb (100-51200 MB)
// - SimPlanChangeRequest: newPlanCode, assignGlobalIp, scheduledAt (YYYYMMDD format)
// - SimCancelRequest: scheduledAt (YYYYMMDD format)

export const simActionsService = {
  async topUp(subscriptionId: string, request: SimTopUpRequest): Promise<void> {
    await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/top-up", {
      params: { path: { subscriptionId } },
      body: request,
    });
  },

  async changePlan(subscriptionId: string, request: SimPlanChangeRequest): Promise<void> {
    await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/change-plan", {
      params: { path: { subscriptionId } },
      body: request,
    });
  },

  async changePlanFull(
    subscriptionId: string,
    request: SimChangePlanFullRequest
  ): Promise<{ scheduledAt?: string }> {
    const response = await apiClient.POST<SimPlanChangeResult>(
      "/api/subscriptions/{subscriptionId}/sim/change-plan-full",
      {
        params: { path: { subscriptionId } },
        body: request,
      }
    );
    const scheduledAt = response.data?.scheduledAt;
    return scheduledAt ? { scheduledAt } : {};
  },

  async cancel(subscriptionId: string, request: SimCancelRequest): Promise<void> {
    await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/cancel", {
      params: { path: { subscriptionId } },
      body: request,
    });
  },

  async cancelFull(subscriptionId: string, request: SimCancelFullRequest): Promise<void> {
    await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/cancel-full", {
      params: { path: { subscriptionId } },
      body: request,
    });
  },

  async getSimInfo(subscriptionId: string): Promise<SimInfo | null> {
    const response = await apiClient.GET<SimInfo>("/api/subscriptions/{subscriptionId}/sim", {
      params: { path: { subscriptionId } },
    });

    if (!response.data) {
      return null;
    }

    return simInfoSchema.parse(response.data);
  },

  async getAvailablePlans(subscriptionId: string): Promise<SimAvailablePlan[]> {
    const response = await apiClient.GET<SimAvailablePlan[]>(
      "/api/subscriptions/{subscriptionId}/sim/available-plans",
      { params: { path: { subscriptionId } } }
    );
    const data = getDataOrDefault(response, []);
    return simAvailablePlanArraySchema.parse(data);
  },

  async getCancellationPreview(subscriptionId: string): Promise<SimCancellationPreview | null> {
    const response = await apiClient.GET<SimCancellationPreview>(
      "/api/subscriptions/{subscriptionId}/sim/cancellation-preview",
      {
        params: { path: { subscriptionId } },
      }
    );
    const data = getDataOrDefault(response, null);
    return data ? simCancellationPreviewSchema.parse(data) : null;
  },

  async reissueSim(subscriptionId: string, request: SimReissueFullRequest): Promise<void> {
    await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/reissue", {
      params: { path: { subscriptionId } },
      body: request,
    });
  },

  // Call/SMS History

  async getDomesticCallHistory(
    subscriptionId: string,
    month?: string,
    page: number = 1,
    limit: number = 50
  ): Promise<SimDomesticCallHistoryResponse | null> {
    const params: Record<string, string> = {};
    if (month) params["month"] = month;
    params["page"] = String(page);
    params["limit"] = String(limit);

    const response = await apiClient.GET<SimDomesticCallHistoryResponse>(
      "/api/subscriptions/{subscriptionId}/sim/call-history/domestic",
      {
        params: { path: { subscriptionId }, query: params },
      }
    );
    const data = getDataOrDefault(response, null);
    return data ? simDomesticCallHistoryResponseSchema.parse(data) : null;
  },

  async getInternationalCallHistory(
    subscriptionId: string,
    month?: string,
    page: number = 1,
    limit: number = 50
  ): Promise<SimInternationalCallHistoryResponse | null> {
    const params: Record<string, string> = {};
    if (month) params["month"] = month;
    params["page"] = String(page);
    params["limit"] = String(limit);

    const response = await apiClient.GET<SimInternationalCallHistoryResponse>(
      "/api/subscriptions/{subscriptionId}/sim/call-history/international",
      {
        params: { path: { subscriptionId }, query: params },
      }
    );
    const data = getDataOrDefault(response, null);
    return data ? simInternationalCallHistoryResponseSchema.parse(data) : null;
  },

  async getSmsHistory(
    subscriptionId: string,
    month?: string,
    page: number = 1,
    limit: number = 50
  ): Promise<SimSmsHistoryResponse | null> {
    const params: Record<string, string> = {};
    if (month) params["month"] = month;
    params["page"] = String(page);
    params["limit"] = String(limit);

    const response = await apiClient.GET<SimSmsHistoryResponse>(
      "/api/subscriptions/{subscriptionId}/sim/sms-history",
      {
        params: { path: { subscriptionId }, query: params },
      }
    );
    const data = getDataOrDefault(response, null);
    return data ? simSmsHistoryResponseSchema.parse(data) : null;
  },

  async getAvailableHistoryMonths(): Promise<string[]> {
    const response = await apiClient.GET<string[]>(
      "/api/subscriptions/sim/call-history/available-months"
    );
    const data = getDataOrDefault(response, []);
    return simHistoryAvailableMonthsSchema.parse(data);
  },
};
