import AsyncStorage from "@react-native-async-storage/async-storage";

export type PointsActivityType =
  | "contact_sync"
  | "send_money"
  | "login"
  | "purchase_ticket"
  | "add_recipient"
  | "share_event"
  | "make_request"
  | "referral_link";

export interface PointsActivityEntry {
  id: string;
  type: PointsActivityType;
  points: number;
  timestamp: string;
  metadata?: Record<string, any>;
}

export interface PointsState {
  total: number;
  activities: PointsActivityEntry[];
}

const STORAGE_KEY = "user_points";

const DEFAULT_STATE: PointsState = {
  total: 0,
  activities: [],
};

export const POINT_VALUES: Record<PointsActivityType, number> = {
  contact_sync: 10,
  send_money: 10,
  login: 5,
  purchase_ticket: 15,
  add_recipient: 10,
  share_event: 5,
  make_request: 8,
  referral_link: 20,
};

async function loadState(): Promise<PointsState> {
  try {
    const stored = await AsyncStorage.getItem(STORAGE_KEY);
    if (!stored) return DEFAULT_STATE;
    const parsed = JSON.parse(stored);
    if (
      typeof parsed === "object" &&
      parsed !== null &&
      typeof parsed.total === "number" &&
      Array.isArray(parsed.activities)
    ) {
      return parsed as PointsState;
    }
    return DEFAULT_STATE;
  } catch (error) {
    if (__DEV__) {
      console.warn("[pointsService] Failed to load state", error);
    }
    return DEFAULT_STATE;
  }
}

async function saveState(state: PointsState): Promise<void> {
  try {
    await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(state));
  } catch (error) {
    if (__DEV__) {
      console.warn("[pointsService] Failed to save state", error);
    }
  }
}

export async function getPointsState(): Promise<PointsState> {
  return loadState();
}

export async function awardPoints(
  type: PointsActivityType,
  metadata?: Record<string, any>
): Promise<PointsState> {
  const current = await loadState();
  const delta = POINT_VALUES[type] ?? 0;

  const entry: PointsActivityEntry = {
    id: `${type}-${Date.now()}`,
    type,
    points: delta,
    timestamp: new Date().toISOString(),
    metadata,
  };

  const next: PointsState = {
    total: current.total + delta,
    activities: [entry, ...current.activities],
  };

  await saveState(next);
  return next;
}

const LOGIN_LAST_AWARD_KEY = "user_points_login_last_award";
const CONTACT_SYNC_AWARDED_KEY = "user_points_contact_sync_awarded";

export async function awardDailyLoginPoints(
  metadata?: Record<string, any>
): Promise<PointsState> {
  const today = new Date().toISOString().slice(0, 10);

  try {
    const lastAwardDate = await AsyncStorage.getItem(LOGIN_LAST_AWARD_KEY);
    if (lastAwardDate === today) {
      return loadState();
    }
  } catch (error) {
    if (__DEV__) {
      console.warn(
        "[pointsService] Failed to read last login award date",
        error
      );
    }
  }

  const updatedState = await awardPoints("login", metadata);

  try {
    await AsyncStorage.setItem(LOGIN_LAST_AWARD_KEY, today);
  } catch (error) {
    if (__DEV__) {
      console.warn(
        "[pointsService] Failed to save last login award date",
        error
      );
    }
  }

  return updatedState;
}

export async function awardFirstContactSyncPoints(
  metadata?: Record<string, any>
): Promise<PointsState> {
  try {
    const alreadyAwarded = await AsyncStorage.getItem(CONTACT_SYNC_AWARDED_KEY);
    if (alreadyAwarded === "true") {
      return loadState();
    }
  } catch (error) {
    if (__DEV__) {
      console.warn(
        "[pointsService] Failed to read contact sync awarded flag",
        error
      );
    }
  }

  const updatedState = await awardPoints("contact_sync", metadata);

  try {
    await AsyncStorage.setItem(CONTACT_SYNC_AWARDED_KEY, "true");
  } catch (error) {
    if (__DEV__) {
      console.warn(
        "[pointsService] Failed to save contact sync awarded flag",
        error
      );
    }
  }

  return updatedState;
}
