import type {
  AssistantMessageResultState,
  AssistantConversationItem,
  ConnectionState,
  HistoryItem,
  NormalizeResultState,
  PromptState,
  RuntimeRun
} from "../state/types";

const PREFIX = "/api";

async function request<T>(path: string, init?: RequestInit): Promise<T> {
  const response = await fetch(`${PREFIX}${path}`, {
    ...init,
    headers: {
      "Content-Type": "application/json",
      ...(init?.headers ?? {})
    }
  });
  const payload = (await response.json()) as T & { error?: { message?: string } };
  if (!response.ok) {
    const message = (payload as { error?: { message?: string } }).error?.message ?? "Ошибка запроса";
    throw new Error(message);
  }
  return payload;
}

export const apiClient = {
  async testConnection(connection: ConnectionState): Promise<{ ok: boolean; model: string; timestamp: string }> {
    return request("/openai/test-connection", {
      method: "POST",
      body: JSON.stringify({
        apiKey: connection.apiKey,
        model: connection.model,
        baseUrl: connection.baseUrl
      })
    });
  },

  async normalize(params: {
    connection: ConnectionState;
    prompts: PromptState;
    promptVersion?: string;
    query: {
      userQuestion: string;
      periodHint?: string;
      businessContext?: string;
      expectedRoute?: string;
    };
    saveAsTestCase?: boolean;
    useMock?: boolean;
  }): Promise<NormalizeResultState> {
    return request("/normalize", {
      method: "POST",
      body: JSON.stringify({
        apiKey: params.connection.apiKey,
        model: params.connection.model,
        baseUrl: params.connection.baseUrl,
        temperature: params.connection.temperature,
        maxOutputTokens: params.connection.maxOutputTokens,
        promptVersion: params.promptVersion,
        systemPrompt: params.prompts.systemPrompt,
        developerPrompt: params.prompts.developerPrompt,
        domainPrompt: params.prompts.domainPrompt,
        fewShotExamples: params.prompts.fewShotExamples,
        userQuestion: params.query.userQuestion,
        context: {
          period_hint: params.query.periodHint ?? "",
          business_context: params.query.businessContext ?? "",
          expected_route: params.query.expectedRoute ?? ""
        },
        saveAsTestCase: Boolean(params.saveAsTestCase),
        useMock: Boolean(params.useMock)
      })
    });
  },

  async loadHistory(): Promise<{ ok: boolean; items: HistoryItem[] }> {
    return request("/history");
  },

  async loadTrace(traceId: string): Promise<{ ok: boolean; trace: unknown }> {
    return request(`/history/${traceId}`);
  },

  async loadPresets(): Promise<{
    ok: boolean;
    presets: Array<{
      id: string;
      name: string;
      prompt_version: string;
      systemPrompt: string;
      developerPrompt: string;
      domainPrompt: string;
      schemaNotes?: string;
      fewShotExamples?: string;
    }>;
  }> {
    return request("/presets");
  },

  async savePreset(input: {
    id?: string;
    name: string;
    prompt_version?: string;
    systemPrompt: string;
    developerPrompt: string;
    domainPrompt: string;
    schemaNotes?: string;
    fewShotExamples?: string;
  }): Promise<{ ok: boolean }> {
    return request("/presets/save", {
      method: "POST",
      body: JSON.stringify(input)
    });
  },

  async runEval(input: {
    connection: ConnectionState;
    prompts: PromptState;
    promptVersion?: string;
    caseIds?: string[];
    useMock?: boolean;
    mode?: "standard" | "single-pass-strict";
    caseSetFile?: string;
    rawQuestions?: string;
  }): Promise<{ ok: boolean; report: unknown }> {
    return request("/eval/run", {
      method: "POST",
      body: JSON.stringify({
        normalizeConfig: {
          apiKey: input.connection.apiKey,
          model: input.connection.model,
          baseUrl: input.connection.baseUrl,
          temperature: input.connection.temperature,
          maxOutputTokens: input.connection.maxOutputTokens,
          promptVersion: input.promptVersion,
          systemPrompt: input.prompts.systemPrompt,
          developerPrompt: input.prompts.developerPrompt,
          domainPrompt: input.prompts.domainPrompt,
          fewShotExamples: input.prompts.fewShotExamples
        },
        caseIds: input.caseIds,
        useMock: Boolean(input.useMock),
        mode: input.mode ?? "standard",
        caseSetFile: input.caseSetFile,
        rawQuestions: input.rawQuestions
      })
    });
  },

  async startRun(): Promise<{ ok: boolean; run: RuntimeRun; runId: string; sessionId: string; status: string }> {
    return request("/accounting-agent/v1/runs/start", {
      method: "POST",
      body: JSON.stringify({
        initiator: "ndc_operator",
        source: "gui"
      })
    });
  },

  async finishRun(runId: string): Promise<{ ok: boolean; run: RuntimeRun }> {
    return request("/accounting-agent/v1/runs/finish", {
      method: "POST",
      body: JSON.stringify({
        runId,
        status: "DONE",
        source: "gui",
        reason: "Остановлено оператором из GUI"
      })
    });
  },

  async listRuns(): Promise<{ ok: boolean; items: RuntimeRun[] }> {
    return request("/accounting-agent/v1/runs");
  },

  async listResults(): Promise<{ ok: boolean; items: unknown[] }> {
    return request("/accounting-agent/v1/results");
  },

  async runTrace(runId: string): Promise<{ ok: boolean; items: unknown[] }> {
    return request(`/accounting-agent/v1/trace/run/${runId}`);
  },

  async sendAssistantMessage(input: {
    connection: ConnectionState;
    prompts: PromptState;
    userMessage: string;
    sessionId?: string;
    promptVersion?: string;
    context?: {
      periodHint?: string;
      businessContext?: string;
    };
    useMock?: boolean;
  }): Promise<AssistantMessageResultState> {
    return request("/assistant/message", {
      method: "POST",
      body: JSON.stringify({
        session_id: input.sessionId ?? "",
        mode: "assistant",
        message: input.userMessage,
        user_message: input.userMessage,
        apiKey: input.connection.apiKey,
        model: input.connection.model,
        baseUrl: input.connection.baseUrl,
        temperature: input.connection.temperature,
        maxOutputTokens: input.connection.maxOutputTokens,
        promptVersion: input.promptVersion ?? "normalizer_v2_0_2",
        systemPrompt: input.prompts.systemPrompt,
        developerPrompt: input.prompts.developerPrompt,
        domainPrompt: input.prompts.domainPrompt,
        fewShotExamples: input.prompts.fewShotExamples,
        context: {
          period_hint: input.context?.periodHint ?? "",
          business_context: input.context?.businessContext ?? ""
        },
        useMock: Boolean(input.useMock)
      })
    });
  },

  async loadAssistantSession(sessionId: string): Promise<{ ok: boolean; session: { items: AssistantConversationItem[] } }> {
    return request(`/assistant/session/${sessionId}`);
  }
};
