import {
  collection,
  doc,
  getDoc,
  setDoc,
  updateDoc,
  deleteDoc,
  onSnapshot,
  query,
} from 'firebase/firestore';
import { db } from '../lib/firebase';

export type CouponStatus = 'active' | 'inactive' | 'expired';

export interface Coupon {
  id: string; // Document ID / UPPERCASE code
  couponCode: string; // UPPERCASE always
  discountType: 'percentage';
  discountPercent: number; // e.g. 10 for 10%
  status: CouponStatus;
  description: string;
  showOnHome?: boolean; // Whether to display in top promo bar / home
  usageLimit: number | null; // null or number
  totalUsed: number;
  validFrom: string; // YYYY-MM-DD
  validUntil: string; // YYYY-MM-DD
  minimumOrderAmount: number; // e.g. 0 or 1000
  maximumDiscount: number | null; // null or max PKR limit
  createdAt: string; // ISO
  updatedAt: string; // ISO
}

export interface CouponValidationResult {
  isValid: boolean;
  error?: string;
  discountPercent: number;
  discountAmount: number;
  coupon?: Coupon;
}

const COUPONS_STORAGE_KEY = 'tnl_coupons_v1';
const COUPONS_COLLECTION = 'coupons';

// Default initial sample coupons available immediately
export const INITIAL_SAMPLE_COUPONS: Coupon[] = [
  {
    id: 'SAVE10',
    couponCode: 'SAVE10',
    discountType: 'percentage',
    discountPercent: 10,
    status: 'active',
    description: 'Get 10% OFF on all organic & natural products',
    showOnHome: true,
    usageLimit: 500,
    totalUsed: 14,
    validFrom: '2025-01-01',
    validUntil: '2027-12-31',
    minimumOrderAmount: 1000,
    maximumDiscount: 2000,
    createdAt: new Date(Date.now() - 3600000 * 200).toISOString(),
    updatedAt: new Date(Date.now() - 3600000 * 200).toISOString(),
  },
  {
    id: 'FIRST25',
    couponCode: 'FIRST25',
    discountType: 'percentage',
    discountPercent: 25,
    status: 'active',
    description: '25% Special discount for new customer orders',
    showOnHome: true,
    usageLimit: 100,
    totalUsed: 3,
    validFrom: '2025-01-01',
    validUntil: '2027-12-31',
    minimumOrderAmount: 2500,
    maximumDiscount: 3500,
    createdAt: new Date(Date.now() - 3600000 * 150).toISOString(),
    updatedAt: new Date(Date.now() - 3600000 * 150).toISOString(),
  },
  {
    id: 'PFE20',
    couponCode: 'PFE20',
    discountType: 'percentage',
    discountPercent: 20,
    status: 'active',
    description: '20% OFF Special Seasonal Offer',
    showOnHome: false,
    usageLimit: 200,
    totalUsed: 8,
    validFrom: '2025-01-01',
    validUntil: '2027-12-31',
    minimumOrderAmount: 1500,
    maximumDiscount: 2500,
    createdAt: new Date(Date.now() - 3600000 * 100).toISOString(),
    updatedAt: new Date(Date.now() - 3600000 * 100).toISOString(),
  },
  {
    id: 'AUG14',
    couponCode: 'AUG14',
    discountType: 'percentage',
    discountPercent: 14,
    status: 'active',
    description: '14% Independence Celebration Discount',
    showOnHome: true,
    usageLimit: null,
    totalUsed: 42,
    validFrom: '2025-01-01',
    validUntil: '2027-12-31',
    minimumOrderAmount: 0,
    maximumDiscount: null,
    createdAt: new Date(Date.now() - 3600000 * 50).toISOString(),
    updatedAt: new Date(Date.now() - 3600000 * 50).toISOString(),
  },
];

let inMemoryCoupons: Coupon[] = [];

export function normalizeCouponCode(code: string): string {
  return code.trim().toUpperCase().replace(/[^A-Z0-9]/g, '');
}

export function getStoredCoupons(): Coupon[] {
  if (inMemoryCoupons.length > 0) return inMemoryCoupons;
  if (typeof window === 'undefined') return INITIAL_SAMPLE_COUPONS;
  try {
    const raw = localStorage.getItem(COUPONS_STORAGE_KEY);
    if (!raw) {
      saveCouponsLocal(INITIAL_SAMPLE_COUPONS);
      return INITIAL_SAMPLE_COUPONS;
    }
    const parsed = JSON.parse(raw) as Coupon[];
    if (!Array.isArray(parsed) || parsed.length === 0) {
      saveCouponsLocal(INITIAL_SAMPLE_COUPONS);
      return INITIAL_SAMPLE_COUPONS;
    }
    inMemoryCoupons = parsed;
    return parsed;
  } catch (err) {
    console.warn('Error reading coupons from localStorage:', err);
    return INITIAL_SAMPLE_COUPONS;
  }
}

export function saveCouponsLocal(list: Coupon[]): void {
  inMemoryCoupons = list;
  if (typeof window === 'undefined') return;
  try {
    localStorage.setItem(COUPONS_STORAGE_KEY, JSON.stringify(list));
  } catch (err) {
    console.warn('Error saving coupons to localStorage:', err);
  }
}

// Real-time Firestore Subscription
export function subscribeToCoupons(callback: (coupons: Coupon[]) => void): () => void {
  callback(getStoredCoupons());
  try {
    const q = query(collection(db, COUPONS_COLLECTION));
    const unsub = onSnapshot(
      q,
      (snapshot) => {
        const fireMap = new Map<string, Coupon>();
        snapshot.forEach((docSnap) => {
          const data = docSnap.data() as Coupon;
          const code = normalizeCouponCode(docSnap.id || data.couponCode);
          if (code) {
            fireMap.set(code, {
              id: code,
              couponCode: code,
              discountType: 'percentage',
              discountPercent: Number(data.discountPercent) || 0,
              status: data.status || 'active',
              description: data.description || '',
              showOnHome: data.showOnHome !== undefined ? Boolean(data.showOnHome) : true,
              usageLimit: data.usageLimit !== undefined ? data.usageLimit : null,
              totalUsed: Number(data.totalUsed) || 0,
              validFrom: data.validFrom || '2025-01-01',
              validUntil: data.validUntil || '2030-12-31',
              minimumOrderAmount: Number(data.minimumOrderAmount) || 0,
              maximumDiscount: data.maximumDiscount !== undefined ? data.maximumDiscount : null,
              createdAt: data.createdAt || new Date().toISOString(),
              updatedAt: data.updatedAt || new Date().toISOString(),
            });
          }
        });

        const localList = getStoredCoupons();
        const mergedMap = new Map<string, Coupon>();
        localList.forEach((c) => mergedMap.set(c.couponCode, c));
        fireMap.forEach((c, code) => mergedMap.set(code, c));

        const result = Array.from(mergedMap.values());
        result.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());

        saveCouponsLocal(result);
        callback(result);
      },
      (err) => {
        console.warn('Firestore coupons subscription error:', err);
        callback(getStoredCoupons());
      }
    );
    return unsub;
  } catch (err) {
    console.warn('Failed subscribing to coupons:', err);
    return () => {};
  }
}

// Validate Coupon Code against order subtotal
export function validateCoupon(rawCode: string, orderSubtotal: number): CouponValidationResult {
  const cleanCode = normalizeCouponCode(rawCode);
  if (!cleanCode) {
    return { isValid: false, error: 'Please enter a coupon code.', discountPercent: 0, discountAmount: 0 };
  }

  const allCoupons = getStoredCoupons();
  const coupon = allCoupons.find((c) => c.couponCode === cleanCode || c.id === cleanCode);

  if (!coupon) {
    return { isValid: false, error: `Invalid coupon code "${cleanCode}".`, discountPercent: 0, discountAmount: 0 };
  }

  if (coupon.status !== 'active') {
    return { isValid: false, error: `Coupon "${cleanCode}" is currently inactive.`, discountPercent: 0, discountAmount: 0 };
  }

  // Date Check
  const todayStr = new Date().toISOString().split('T')[0];
  if (coupon.validFrom && todayStr < coupon.validFrom) {
    return { isValid: false, error: `Coupon "${cleanCode}" is not active yet.`, discountPercent: 0, discountAmount: 0 };
  }
  if (coupon.validUntil && todayStr > coupon.validUntil) {
    return { isValid: false, error: `Coupon "${cleanCode}" has expired.`, discountPercent: 0, discountAmount: 0 };
  }

  // Usage Limit Check
  if (coupon.usageLimit !== null && coupon.usageLimit > 0 && coupon.totalUsed >= coupon.usageLimit) {
    return { isValid: false, error: `Coupon "${cleanCode}" usage limit has been reached.`, discountPercent: 0, discountAmount: 0 };
  }

  // Minimum Order Amount Check
  if (coupon.minimumOrderAmount > 0 && orderSubtotal < coupon.minimumOrderAmount) {
    return {
      isValid: false,
      error: `Minimum order amount of Rs ${coupon.minimumOrderAmount.toLocaleString('en-PK')} required for this coupon.`,
      discountPercent: 0,
      discountAmount: 0,
    };
  }

  // Calculate Discount Amount
  let rawDiscount = (orderSubtotal * coupon.discountPercent) / 100;
  if (coupon.maximumDiscount !== null && coupon.maximumDiscount > 0) {
    rawDiscount = Math.min(rawDiscount, coupon.maximumDiscount);
  }

  const discountAmount = Math.round(rawDiscount);

  return {
    isValid: true,
    discountPercent: coupon.discountPercent,
    discountAmount,
    coupon,
  };
}

// Increment totalUsed for applied coupon
export async function applyCouponUsage(rawCode: string): Promise<void> {
  const code = normalizeCouponCode(rawCode);
  if (!code) return;

  const current = getStoredCoupons();
  const updatedList = current.map((c) => {
    if (c.couponCode === code) {
      return { ...c, totalUsed: (c.totalUsed || 0) + 1, updatedAt: new Date().toISOString() };
    }
    return c;
  });
  saveCouponsLocal(updatedList);

  try {
    const docRef = doc(db, COUPONS_COLLECTION, code);
    const snap = await getDoc(docRef);
    if (snap.exists()) {
      const data = snap.data() as Coupon;
      const newTotal = (data.totalUsed || 0) + 1;
      await updateDoc(docRef, { totalUsed: newTotal, updatedAt: new Date().toISOString() });
    }
  } catch (err) {
    console.warn('Error incrementing coupon usage in Firestore:', err);
  }
}

// Create or Edit Coupon
export async function saveCoupon(couponData: Omit<Coupon, 'createdAt' | 'updatedAt'> & { id?: string }): Promise<Coupon> {
  const code = normalizeCouponCode(couponData.couponCode);
  if (!code) throw new Error('Coupon code cannot be empty.');

  const now = new Date().toISOString();
  const currentList = getStoredCoupons();
  const existing = currentList.find((c) => c.couponCode === code);

  const newCoupon: Coupon = {
    id: code,
    couponCode: code,
    discountType: 'percentage',
    discountPercent: Number(couponData.discountPercent) || 0,
    status: couponData.status || 'active',
    description: couponData.description || '',
    showOnHome: couponData.showOnHome !== undefined ? Boolean(couponData.showOnHome) : true,
    usageLimit: couponData.usageLimit !== undefined ? couponData.usageLimit : null,
    totalUsed: existing ? existing.totalUsed : Number(couponData.totalUsed) || 0,
    validFrom: couponData.validFrom || new Date().toISOString().split('T')[0],
    validUntil: couponData.validUntil || '2030-12-31',
    minimumOrderAmount: Number(couponData.minimumOrderAmount) || 0,
    maximumDiscount: couponData.maximumDiscount !== undefined ? couponData.maximumDiscount : null,
    createdAt: existing ? existing.createdAt : now,
    updatedAt: now,
  };

  const updatedList = existing
    ? currentList.map((c) => (c.couponCode === code ? newCoupon : c))
    : [newCoupon, ...currentList];

  saveCouponsLocal(updatedList);

  try {
    const docRef = doc(db, COUPONS_COLLECTION, code);
    await setDoc(docRef, newCoupon, { merge: true });
  } catch (err) {
    console.warn('Error saving coupon to Firestore:', err);
  }

  return newCoupon;
}

// Delete Coupon
export async function deleteCoupon(rawCode: string): Promise<void> {
  const code = normalizeCouponCode(rawCode);
  if (!code) return;

  const filtered = getStoredCoupons().filter((c) => c.couponCode !== code);
  saveCouponsLocal(filtered);

  try {
    const docRef = doc(db, COUPONS_COLLECTION, code);
    await deleteDoc(docRef);
  } catch (err) {
    console.warn('Error deleting coupon from Firestore:', err);
  }
}
