import * as SecureStore from 'expo-secure-store';
import * as Crypto from 'expo-crypto';
import type { AuthResponse, ChatResponse, Beneficiary, ApiResponse, ApiError, DashboardSingleResponse, BeneficiaryDashboardData } from '@/types';

// Callback for handling unauthorized responses (401)
let onUnauthorizedCallback: (() => void) | null = null;

export function setOnUnauthorizedCallback(callback: () => void) {
  onUnauthorizedCallback = callback;
}

const API_BASE_URL = 'https://eluxnetworks.net/function/well-api/api';
const CLIENT_ID = 'MA_001';

// Avatar images for elderly beneficiaries - grandmothers (бабушки)
const ELDERLY_AVATARS = [
  'https://images.unsplash.com/photo-1566616213894-2d4e1baee5d8?w=200&h=200&fit=crop&crop=face', // grandmother with gray hair
  'https://images.unsplash.com/photo-1544027993-37dbfe43562a?w=200&h=200&fit=crop&crop=face', // elderly woman smiling
  'https://images.unsplash.com/photo-1491308056676-205b7c9a7dc1?w=200&h=200&fit=crop&crop=face', // senior woman portrait
  'https://images.unsplash.com/photo-1580489944761-15a19d654956?w=200&h=200&fit=crop&crop=face', // older woman glasses
  'https://images.unsplash.com/photo-1548142813-c348350df52b?w=200&h=200&fit=crop&crop=face', // grandmother portrait
];

// Get consistent avatar based on deployment_id
function getAvatarForBeneficiary(deploymentId: number): string {
  const index = deploymentId % ELDERLY_AVATARS.length;
  return ELDERLY_AVATARS[index];
}

// Helper function to format time ago
function formatTimeAgo(date: Date): string {
  const now = new Date();
  const diffMs = now.getTime() - date.getTime();
  const diffMins = Math.floor(diffMs / 60000);
  const diffHours = Math.floor(diffMins / 60);
  const diffDays = Math.floor(diffHours / 24);

  if (diffMins < 1) return 'Just now';
  if (diffMins < 60) return `${diffMins} min ago`;
  if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;
  return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;
}

class ApiService {
  private async getToken(): Promise<string | null> {
    try {
      return await SecureStore.getItemAsync('accessToken');
    } catch {
      return null;
    }
  }

  private async getUserName(): Promise<string | null> {
    try {
      return await SecureStore.getItemAsync('userName');
    } catch {
      return null;
    }
  }

  private generateNonce(): string {
    const randomBytes = Crypto.getRandomBytes(16);
    return Array.from(randomBytes)
      .map(b => b.toString(16).padStart(2, '0'))
      .join('');
  }

  private async makeRequest<T>(params: Record<string, string>): Promise<ApiResponse<T>> {
    try {
      const formData = new URLSearchParams();
      Object.entries(params).forEach(([key, value]) => {
        formData.append(key, value);
      });

      const response = await fetch(API_BASE_URL, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: formData.toString(),
      });

      const data = await response.json();

      // Handle 401 Unauthorized - trigger logout
      if (response.status === 401 || data.status === '401' || data.error === 'Unauthorized') {
        if (onUnauthorizedCallback) {
          onUnauthorizedCallback();
        }
        return {
          ok: false,
          error: {
            message: 'Session expired. Please login again.',
            code: 'UNAUTHORIZED',
            status: 401,
          },
        };
      }

      if (data.status === '200 OK' || data.ok === true) {
        return { data: data as T, ok: true };
      }

      return {
        ok: false,
        error: {
          message: data.message || data.error || 'Request failed',
          status: response.status,
        },
      };
    } catch (error) {
      const apiError: ApiError = {
        message: error instanceof Error ? error.message : 'Network error',
        code: 'NETWORK_ERROR',
      };
      return { ok: false, error: apiError };
    }
  }

  // Authentication
  async login(username: string, password: string): Promise<ApiResponse<AuthResponse>> {
    const response = await this.makeRequest<AuthResponse>({
      function: 'credentials',
      user_name: username,
      ps: password,
      clientId: CLIENT_ID,
      nonce: this.generateNonce(),
    });

    if (response.ok && response.data) {
      // Save credentials to SecureStore
      await SecureStore.setItemAsync('accessToken', response.data.access_token);
      await SecureStore.setItemAsync('userId', response.data.user_id.toString());
      await SecureStore.setItemAsync('userName', username);
      await SecureStore.setItemAsync('privileges', response.data.privileges);
      await SecureStore.setItemAsync('maxRole', response.data.max_role.toString());
    }

    return response;
  }

  async logout(): Promise<void> {
    await SecureStore.deleteItemAsync('accessToken');
    await SecureStore.deleteItemAsync('userId');
    await SecureStore.deleteItemAsync('userName');
    await SecureStore.deleteItemAsync('privileges');
    await SecureStore.deleteItemAsync('maxRole');
  }

  async isAuthenticated(): Promise<boolean> {
    const token = await this.getToken();
    return !!token;
  }

  // Get stored user info
  async getStoredUser() {
    try {
      const userId = await SecureStore.getItemAsync('userId');
      const userName = await SecureStore.getItemAsync('userName');
      const privileges = await SecureStore.getItemAsync('privileges');
      const maxRole = await SecureStore.getItemAsync('maxRole');

      if (!userId || !userName) return null;

      return {
        user_id: parseInt(userId, 10),
        user_name: userName,
        privileges: privileges || '',
        max_role: parseInt(maxRole || '0', 10),
      };
    } catch {
      return null;
    }
  }

  // Beneficiaries (elderly people being monitored)
  async getBeneficiaries(): Promise<ApiResponse<{ beneficiaries: Beneficiary[] }>> {
    const token = await this.getToken();
    if (!token) {
      return { ok: false, error: { message: 'Not authenticated', code: 'UNAUTHORIZED' } };
    }

    // Note: Using mock data since API structure is not fully documented
    // Replace with actual API call when available
    const mockBeneficiaries: Beneficiary[] = [
      {
        id: 1,
        name: 'Julia Smith',
        status: 'online',
        relationship: 'Mother',
        last_activity: '2 min ago',
        sensor_data: {
          motion_detected: true,
          last_motion: '2 min ago',
          door_status: 'closed',
          temperature: 22,
          humidity: 45,
        },
      },
      {
        id: 2,
        name: 'Robert Johnson',
        status: 'offline',
        relationship: 'Father',
        last_activity: '1 hour ago',
        sensor_data: {
          motion_detected: false,
          last_motion: '1 hour ago',
          door_status: 'closed',
          temperature: 21,
          humidity: 50,
        },
      },
    ];

    return { data: { beneficiaries: mockBeneficiaries }, ok: true };
  }

  async getBeneficiary(id: number): Promise<ApiResponse<Beneficiary>> {
    // Use real API data via getBeneficiaryDashboard
    const response = await this.getBeneficiaryDashboard(id.toString());

    if (!response.ok || !response.data) {
      return { ok: false, error: response.error || { message: 'Beneficiary not found', code: 'NOT_FOUND' } };
    }

    const data = response.data;
    // Determine if beneficiary is "online" based on last_detected_time
    const lastDetected = data.last_detected_time ? new Date(data.last_detected_time) : null;
    const isRecent = lastDetected && (Date.now() - lastDetected.getTime()) < 30 * 60 * 1000; // 30 min

    const deploymentId = parseInt(data.deployment_id, 10);
    const beneficiary: Beneficiary = {
      id: deploymentId,
      name: data.name,
      avatar: getAvatarForBeneficiary(deploymentId),
      status: isRecent ? 'online' : 'offline',
      address: data.address,
      timezone: data.time_zone,
      wellness_score: data.wellness_score_percent,
      wellness_descriptor: data.wellness_descriptor,
      last_location: data.last_location,
      temperature: data.temperature,
      units: data.units,
      sleep_hours: data.sleep_hours,
      bedroom_temperature: data.bedroom_temperature,
      before_last_location: data.before_last_location,
      last_detected_time: data.last_detected_time,
      last_activity: data.last_detected_time
        ? formatTimeAgo(new Date(data.last_detected_time))
        : undefined,
    };

    return { data: beneficiary, ok: true };
  }

  // Get beneficiary dashboard data by deployment_id
  async getBeneficiaryDashboard(deploymentId: string): Promise<ApiResponse<BeneficiaryDashboardData>> {
    const token = await this.getToken();
    const userName = await this.getUserName();

    if (!token || !userName) {
      return { ok: false, error: { message: 'Not authenticated', code: 'UNAUTHORIZED' } };
    }

    const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD

    const response = await this.makeRequest<DashboardSingleResponse>({
      function: 'dashboard_single',
      user_name: userName,
      token: token,
      deployment_id: deploymentId,
      date: today,
      nonce: this.generateNonce(),
    });

    if (response.ok && response.data?.result_list?.[0]) {
      return { data: response.data.result_list[0], ok: true };
    }

    return {
      ok: false,
      error: response.error || { message: 'Failed to get beneficiary data' },
    };
  }

  // Get all beneficiaries using deployments_list API (single fast request)
  async getAllBeneficiaries(): Promise<ApiResponse<Beneficiary[]>> {
    const token = await this.getToken();
    const userName = await this.getUserName();

    if (!token || !userName) {
      return { ok: false, error: { message: 'Not authenticated', code: 'UNAUTHORIZED' } };
    }

    // Use deployments_list API - single request for all beneficiaries
    const response = await this.makeRequest<{ result_list: Array<{
      deployment_id: number;
      email: string;
      first_name: string;
      last_name: string;
    }> }>({
      function: 'deployments_list',
      user_name: userName,
      token: token,
      first: '0',
      last: '100',
    });

    if (!response.ok || !response.data?.result_list) {
      return { ok: false, error: response.error || { message: 'Failed to get beneficiaries' } };
    }

    const beneficiaries: Beneficiary[] = response.data.result_list.map(item => ({
      id: item.deployment_id,
      name: `${item.first_name} ${item.last_name}`.trim(),
      avatar: getAvatarForBeneficiary(item.deployment_id),
      status: 'offline' as const, // Will be updated when dashboard is loaded
      email: item.email,
    }));

    return { data: beneficiaries, ok: true };
  }

  // AI Chat - deploymentId is required, no default value for security
  async sendMessage(question: string, deploymentId: string): Promise<ApiResponse<ChatResponse>> {
    if (!deploymentId) {
      return { ok: false, error: { message: 'Please select a beneficiary first', code: 'NO_BENEFICIARY_SELECTED' } };
    }
    const token = await this.getToken();
    const userName = await this.getUserName();

    if (!token || !userName) {
      return { ok: false, error: { message: 'Not authenticated', code: 'UNAUTHORIZED' } };
    }

    return this.makeRequest<ChatResponse>({
      function: 'voice_ask',
      clientId: CLIENT_ID,
      user_name: userName,
      token: token,
      question: question,
      deployment_id: deploymentId,
    });
  }
}

export const api = new ApiService();
