import axios, { AxiosInstance } from 'axios';
import {
  User,
  Quest,
  Member,
  Location,
  LoginRequest,
  SignupRequest,
  LoginResponse,
  SutStatus,
  NpcCharacter,
  NpcChatResponse,
  NpcSuggestedQuest,
  ShopItem,
  InventoryItem,
  BargainStats,
} from '../types';

// Determine API URL based on environment and current location
// Always route through Caddy proxy (port 80) for consistent CORS handling
// Type declaration for webpack's process.env
interface ProcessEnv {
  REACT_APP_API_URL?: string;
}

declare const process: {
  env: ProcessEnv;
};

const getApiUrl = (): string => {
  // React apps use webpack's DefinePlugin which replaces process.env at build time
  const envUrl = process.env.REACT_APP_API_URL;
  
  // If environment variable is a full URL, use it
  if (envUrl && envUrl.startsWith('http')) {
    return envUrl;
  }
  
  // Detect if running in development mode (direct access to port 3000)
  // vs production/test mode (accessed through Caddy on port 80)
  if (typeof window !== 'undefined') {
    const port = window.location.port;
    const hostname = window.location.hostname;
    
    // If accessed directly on port 3000, route API calls through Caddy on port 80
    // Otherwise use relative path which works through Caddy proxy
    if (port === '3000') {
      return `http://${hostname}/api`;
    }
  }
  
  // Default: use relative path /api
  // This works when accessed via Caddy on port 80 (production/tests)
  return envUrl || '/api';
};

const API_URL = getApiUrl();

class ApiService {
  private api: AxiosInstance;

  constructor() {
    this.api = axios.create({
      baseURL: API_URL,
      withCredentials: true,
      headers: {
        'Content-Type': 'application/json',
      },
    });
  }

  // Authentication
  async login(credentials: LoginRequest): Promise<LoginResponse> {
    const response = await this.api.post<LoginResponse>('/auth/login', credentials);
    return response.data;
  }

  async signup(payload: SignupRequest): Promise<LoginResponse> {
    const response = await this.api.post<LoginResponse>('/auth/signup', payload);
    return response.data;
  }

  async logout(): Promise<void> {
    await this.api.post('/auth/logout');
  }

  async getCurrentUser(): Promise<User> {
    const response = await this.api.get<User>('/auth/me');
    return response.data;
  }

  async getSutStatus(): Promise<SutStatus> {
    const response = await this.api.get<SutStatus>('/status');
    return response.data;
  }

  // Quests
  async getQuests(filters?: {
    status?: string;
    quest_type?: string;
    priority?: string;
    dark_magic?: boolean;
    location_id?: number;
    assigned_to?: number;
  }): Promise<Quest[]> {
    const params = new URLSearchParams();
    if (filters) {
      if (filters.status) params.append('status', filters.status);
      if (filters.quest_type) params.append('quest_type', filters.quest_type);
      if (filters.priority) params.append('priority', filters.priority);
      if (filters.dark_magic !== undefined) params.append('dark_magic', filters.dark_magic.toString());
      if (filters.location_id) params.append('location_id', filters.location_id.toString());
      if (filters.assigned_to) params.append('assigned_to', filters.assigned_to.toString());
    }
    const queryString = params.toString();
    const url = queryString ? `/quests/?${queryString}` : '/quests/';
    const response = await this.api.get<Quest[]>(url);
    return response.data;
  }

  async getQuest(id: number): Promise<Quest> {
    const response = await this.api.get<Quest>(`/quests/${id}`);
    return response.data;
  }

  async createQuest(quest: Partial<Quest>): Promise<Quest> {
    const response = await this.api.post<Quest>('/quests/', quest);
    return response.data;
  }

  async updateQuest(id: number, quest: Partial<Quest>): Promise<Quest> {
    const response = await this.api.put<Quest>(`/quests/${id}`, quest);
    return response.data;
  }

  async deleteQuest(id: number): Promise<void> {
    await this.api.delete(`/quests/${id}`);
  }

  async completeQuest(id: number): Promise<Quest & { message?: string }> {
    const response = await this.api.put<Quest & { message?: string }>(`/quests/${id}/complete`);
    return response.data;
  }

  // Members
  async getMembers(): Promise<Member[]> {
    const response = await this.api.get<Member[]>('/members/');
    return response.data;
  }

  async getMember(id: number): Promise<Member> {
    const response = await this.api.get<Member>(`/members/${id}`);
    return response.data;
  }

  // Locations
  async getLocations(): Promise<Location[]> {
    const response = await this.api.get<Location[]>('/locations/');
    return response.data;
  }

  async getLocation(id: number): Promise<Location> {
    const response = await this.api.get<Location>(`/locations/${id}`);
    return response.data;
  }

  // NPC Chat
  async startNpcChat(character: NpcCharacter): Promise<NpcChatResponse> {
    const response = await this.api.post<NpcChatResponse>('/chat/start', { character });
    return response.data;
  }

  async sendNpcMessage(character: NpcCharacter, message: string): Promise<NpcChatResponse> {
    const response = await this.api.post<NpcChatResponse>('/chat/message', { character, message });
    return response.data;
  }

  async getNpcChatSession(character: NpcCharacter): Promise<NpcChatResponse> {
    const response = await this.api.get<NpcChatResponse>(`/chat/session?character=${character}`);
    return response.data;
  }

  async resetNpcChat(character: NpcCharacter): Promise<NpcChatResponse> {
    const response = await this.api.post<NpcChatResponse>('/chat/reset', { character });
    return response.data;
  }

  async createQuestFromNpc(
    character: NpcCharacter,
    quest: NpcSuggestedQuest
  ): Promise<{ quest: Quest; message: string }> {
    const response = await this.api.post<{ quest: Quest; message: string }>('/chat/create_quest', {
      character,
      ...quest,
    });
    return response.data;
  }

  // Bargaining shop
  async getShopItems(character?: string): Promise<ShopItem[]> {
    const suffix = character ? `?character=${encodeURIComponent(character)}` : '';
    const response = await this.api.get<{ items: ShopItem[] }>(`/shop/items${suffix}`);
    return response.data.items;
  }

  async purchaseItem(itemId: number, paidPrice: number): Promise<{
    purchase: InventoryItem;
    balance: { gold: number };
    deal_quality: 'good' | 'fair' | 'bad';
  }> {
    const response = await this.api.post('/shop/purchase', {
      item_id: itemId,
      paid_price: paidPrice,
    });
    return response.data;
  }

  async getInventory(): Promise<InventoryItem[]> {
    const response = await this.api.get<{ inventory: InventoryItem[] }>('/shop/inventory');
    return response.data.inventory;
  }

  async getBargainStats(): Promise<BargainStats> {
    const response = await this.api.get<{ stats: BargainStats }>('/shop/stats');
    return response.data.stats;
  }

  async getGoldBalance(): Promise<number> {
    const response = await this.api.get<{ gold: number }>('/shop/balance');
    return response.data.gold;
  }
}

export const apiService = new ApiService();
