import { Page } from '@playwright/test';
import type { AdminOrder, Product } from '../../types';

const jsonResponse = (data: unknown, status = 200) => ({
  status,
  contentType: 'application/json',
  body: JSON.stringify(data),
});

export const mockShopApi = async (page: Page) => {
  await page.route('**/api/category-images**', async (route) => {
    await route.fulfill(jsonResponse([]));
  });

  await page.route('**/api/products**', async (route) => {
    await route.fulfill(jsonResponse([]));
  });

  await page.route('**/api/reviews**', async (route) => {
    const method = route.request().method();
    if (method === 'GET') {
      await route.fulfill(jsonResponse([]));
      return;
    }

    if (method === 'POST') {
      let payload: { author?: string; rating?: number; text?: string } = {};
      try {
        payload = route.request().postDataJSON() as typeof payload;
      } catch {
        payload = {};
      }

      const createdReview = {
        id: 'review-e2e',
        author: payload.author ?? 'Testaaja',
        rating: payload.rating ?? 5,
        text: payload.text ?? 'Hyvä kokemus!',
        status: 'pending',
        date: new Date().toISOString(),
      };

      await route.fulfill(jsonResponse(createdReview, 201));
      return;
    }

    await route.fulfill(jsonResponse([]));
  });

  await page.route('**/api/orders**', async (route) => {
    const method = route.request().method();
    if (method === 'POST') {
      let payload: {
        customer?: Record<string, string>;
        items?: unknown[];
        total?: number;
        shippingMethod?: string;
      } = {};
      try {
        payload = route.request().postDataJSON() as typeof payload;
      } catch {
        payload = {};
      }

      const createdOrder = {
        id: 'order-e2e',
        customer: payload.customer ?? {
          name: 'Testaaja',
          email: 'test@example.com',
          phone: '040 000 0000',
          address: 'Testikatu 1',
          city: 'Helsinki',
          zip: '00100',
          notes: '',
        },
        items: payload.items ?? [],
        total: payload.total ?? 0,
        status: 'pending',
        shippingMethod: payload.shippingMethod ?? 'postitus',
        date: new Date().toISOString(),
      };

      await route.fulfill(jsonResponse(createdOrder, 201));
      return;
    }

    await route.fulfill(jsonResponse([]));
  });
};

export type OrderStore = {
  orders: AdminOrder[];
};

export const setupOrderAdminMocks = async (page: Page, products: Product[]) => {
  const store: OrderStore = { orders: [] };
  const productsById = new Map(products.map((product) => [product.id, product]));
  let orderSequence = 1;

  const toNumber = (value: unknown) => {
    if (typeof value === 'number') return value;
    if (typeof value === 'string') return Number(value);
    return 0;
  };

  const buildAdminOrder = (payload: {
    customer?: Record<string, string>;
    items?: Array<{
      id: string;
      quantity: number;
      price: number;
      salePrice?: number;
      selectedColor?: string | null;
      selectedSize?: string | null;
    }>;
    total?: number | string;
    shippingMethod?: string;
  }) => {
    const orderId = `order-${orderSequence++}`;
    const customer = payload.customer ?? {};
    const items = (payload.items ?? []).map((item, index) => {
      const product = productsById.get(item.id) ?? {
        id: item.id,
        name: 'Tuntematon tuote',
        price: item.price,
        category: '',
        subcategory: '',
        shortDescription: '',
        description: '',
        images: [],
        stock: 0,
      };
      const itemPrice = toNumber(item.salePrice ?? item.price ?? product.price);

      return {
        id: `item-${orderId}-${index}`,
        quantity: item.quantity ?? 1,
        price: itemPrice,
        selectedColor: item.selectedColor ?? null,
        selectedSize: item.selectedSize ?? null,
        product,
      };
    });

    const total = toNumber(payload.total ?? 0);

    const adminOrder: AdminOrder = {
      id: orderId,
      customerName: customer.name ?? 'Testaaja',
      customerEmail: customer.email ?? 'test@example.com',
      customerPhone: customer.phone ?? '040 000 0000',
      customerAddress: customer.address ?? 'Testikatu 1',
      customerCity: customer.city ?? 'Helsinki',
      customerZip: customer.zip ?? '00100',
      notes: customer.notes ?? null,
      total,
      status: 'pending',
      shippingMethod: payload.shippingMethod ?? 'postitus',
      createdAt: new Date(),
      items,
    };

    return adminOrder;
  };

  await page.route('**/api/auth/session', async (route) => {
    await route.fulfill(
      jsonResponse({
        user: {
          email: 'admin@varjoliitokauppa.fi',
          name: 'Admin',
        },
        expires: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
      }),
    );
  });

  await page.route('**/api/auth/csrf', async (route) => {
    await route.fulfill(jsonResponse({ csrfToken: 'test-csrf' }));
  });

  await page.route('**/api/auth/providers', async (route) => {
    await route.fulfill(
      jsonResponse({
        credentials: {
          id: 'credentials',
          name: 'Credentials',
          type: 'credentials',
        },
      }),
    );
  });

  await page.route('**/api/category-images', async (route) => {
    await route.fulfill(jsonResponse([]));
  });

  await page.route('**/api/admin/category-images', async (route) => {
    await route.fulfill(jsonResponse([]));
  });

  await page.route('**/api/products', async (route) => {
    await route.fulfill(jsonResponse(products));
  });

  await page.route('**/api/reviews', async (route) => {
    await route.fulfill(jsonResponse([]));
  });

  await page.route('**/api/admin/reviews', async (route) => {
    await route.fulfill(jsonResponse([]));
  });

  await page.route('**/api/orders', async (route) => {
    const method = route.request().method();
    if (method !== 'POST') {
      await route.fulfill(jsonResponse([]));
      return;
    }

    let payload: {
      customer?: Record<string, string>;
      items?: Array<{
        id: string;
        quantity: number;
        price: number;
        salePrice?: number;
        selectedColor?: string | null;
        selectedSize?: string | null;
      }>;
      total?: number | string;
      shippingMethod?: string;
    } = {};
    try {
      payload = route.request().postDataJSON() as typeof payload;
    } catch {
      payload = {};
    }

    const adminOrder = buildAdminOrder(payload);
    store.orders = [adminOrder, ...store.orders];

    const publicOrder = {
      id: adminOrder.id,
      customer: payload.customer ?? {
        name: adminOrder.customerName,
        email: adminOrder.customerEmail,
        phone: adminOrder.customerPhone,
        address: adminOrder.customerAddress,
        city: adminOrder.customerCity,
        zip: adminOrder.customerZip,
        notes: adminOrder.notes ?? '',
      },
      items: payload.items ?? [],
      total: adminOrder.total,
      status: adminOrder.status,
      shippingMethod: adminOrder.shippingMethod,
      date: new Date().toISOString(),
    };

    await route.fulfill(jsonResponse(publicOrder, 201));
  });

  await page.route('**/api/admin/orders**', async (route) => {
    const method = route.request().method();
    const url = new URL(route.request().url());
    const { pathname } = url;

    if (pathname.endsWith('/api/admin/orders')) {
      await route.fulfill(jsonResponse(store.orders));
      return;
    }

    if (pathname.includes('/api/admin/orders/')) {
      const orderId = pathname.split('/').pop() ?? '';
      const order = store.orders.find((item) => item.id === orderId);

      if (!order) {
        await route.fulfill(jsonResponse({ error: 'Order not found' }, 404));
        return;
      }

      if (method === 'GET') {
        await route.fulfill(jsonResponse(order));
        return;
      }

      if (method === 'PUT') {
        let payload: { status?: string } = {};
        try {
          payload = route.request().postDataJSON() as typeof payload;
        } catch {
          payload = {};
        }

        if (payload.status) {
          order.status = payload.status as AdminOrder['status'];
        }

        await route.fulfill(jsonResponse(order));
        return;
      }

      await route.fulfill(jsonResponse(order));
      return;
    }

    await route.fulfill(jsonResponse([]));
  });

  return store;
};

export const addProductToCart = async (page: Page, productName: string) => {
  const productHeading = page.getByRole('heading', { name: productName }).first();
  await productHeading.waitFor({ state: 'visible' });

  const card = productHeading.locator('xpath=ancestor::*[@data-testid="product-card"][1]');

  await card.getByRole('button', { name: 'Lisää koriin' }).click();
};

export const fillContactForm = async (page: Page) => {
  await page.locator('label:has-text("Nimi")').locator('..').locator('input').fill('Testi Asiakas');
  await page.locator('label:has-text("Sähköposti")').locator('..').locator('input').fill('testi@example.com');
  await page.locator('label:has-text("Puhelin")').locator('..').locator('input').fill('040 123 4567');
  await page.locator('label:has-text("Aihe")').locator('..').locator('select').selectOption({ label: 'Tilauskysely' });
  await page.locator('label:has-text("Viesti")').locator('..').locator('textarea').fill('Hei! Voinko saada lisätietoja valjaista?');
};
