import { nanoid } from "nanoid";
import type { AssistantConversationItem, AssistantSessionState } from "../types/assistant";
import type { InvestigationState } from "../types/stage1Contracts";
import { FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 } from "../config";
import { cloneInvestigationState, createEmptyInvestigationState } from "./investigationState";

const MAX_ITEMS_PER_SESSION = 200;

function cloneItem(item: AssistantConversationItem): AssistantConversationItem {
  return {
    ...item,
    debug: item.debug ? { ...item.debug } : null
  };
}

function cloneSession(state: AssistantSessionState): AssistantSessionState {
  return {
    session_id: state.session_id,
    updated_at: state.updated_at,
    items: state.items.map(cloneItem),
    investigation_state: cloneInvestigationState(state.investigation_state)
  };
}

function normalizeSessionShape(state: AssistantSessionState): AssistantSessionState {
  const legacy = state as AssistantSessionState & {
    investigation_state?: InvestigationState | null;
    items?: AssistantConversationItem[];
    updated_at?: string;
  };
  const normalizedItems = Array.isArray(legacy.items) ? legacy.items : [];
  const investigationState =
    FEATURE_ASSISTANT_INVESTIGATION_STATE_V1
      ? legacy.investigation_state ?? createEmptyInvestigationState(state.session_id)
      : legacy.investigation_state ?? null;

  state.items = normalizedItems;
  state.updated_at = typeof legacy.updated_at === "string" && legacy.updated_at.trim() ? legacy.updated_at : new Date().toISOString();
  state.investigation_state = investigationState;
  return state;
}

export class AssistantSessionStore {
  private readonly sessions = new Map<string, AssistantSessionState>();

  public ensureSession(sessionId?: string): AssistantSessionState {
    const resolvedId = (sessionId ?? "").trim() || `asst-${nanoid(10)}`;
    const existing = this.sessions.get(resolvedId);
    if (existing) {
      return cloneSession(normalizeSessionShape(existing));
    }
    const created: AssistantSessionState = {
      session_id: resolvedId,
      updated_at: new Date().toISOString(),
      items: [],
      investigation_state: FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 ? createEmptyInvestigationState(resolvedId) : null
    };
    this.sessions.set(resolvedId, created);
    return cloneSession(created);
  }

  public appendItem(sessionId: string, item: AssistantConversationItem): AssistantConversationItem {
    const session = this.ensureMutableSession(sessionId);
    session.items.push(item);
    if (session.items.length > MAX_ITEMS_PER_SESSION) {
      session.items = session.items.slice(session.items.length - MAX_ITEMS_PER_SESSION);
    }
    session.updated_at = new Date().toISOString();
    return cloneItem(item);
  }

  public getSession(sessionId: string): AssistantSessionState | null {
    const found = this.sessions.get(sessionId);
    return found ? cloneSession(normalizeSessionShape(found)) : null;
  }

  public setInvestigationState(sessionId: string, state: InvestigationState | null): InvestigationState | null {
    const session = this.ensureMutableSession(sessionId);
    session.investigation_state = cloneInvestigationState(state);
    session.updated_at = new Date().toISOString();
    return cloneInvestigationState(session.investigation_state);
  }

  private ensureMutableSession(sessionId: string): AssistantSessionState {
    const existing = this.sessions.get(sessionId);
    if (existing) {
      return normalizeSessionShape(existing);
    }
    const created: AssistantSessionState = {
      session_id: sessionId,
      updated_at: new Date().toISOString(),
      items: [],
      investigation_state: FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 ? createEmptyInvestigationState(sessionId) : null
    };
    this.sessions.set(sessionId, created);
    return created;
  }
}
