<?php

namespace App\Services;

use App\DTOs\Stripe\ProductWithPriceDTO;
use App\Models\SubscriptionPlan;
use App\Models\SubscriptionPrice;
use Illuminate\Http\JsonResponse;
use Stripe\Stripe;
use Illuminate\Http\Response;
use Stripe\Exception\ApiErrorException;
use Exception;
use Stripe\Price;
use Stripe\Product;

class ProductStripeService
{
    public function __construct()
    {
        Stripe::setApiKey(config('app.stripe.secret'));
    }

    public function getPlans(bool $includeInactive = false): JsonResponse
    {
        try {
            $plansQuery = SubscriptionPlan::with(['prices' => function ($query) use ($includeInactive) {
                if (!$includeInactive) {
                    $query->where('is_active', true);
                }
            }]);

            if (!$includeInactive) {
                $plansQuery->where('is_active', true);
            }

            $plans = $plansQuery->limit(100)->get();

            return response()->json([
                'message' => 'Planes obtenidos exitosamente.',
                'plans' => $plans
            ], Response::HTTP_OK);
        } catch (Exception $e) {
            return response()->json(['error' => 'Error al obtener los planes: ' . $e->getMessage(),], 500);
        }
    }

    public function getPlanDetail(string $planId): JsonResponse
    {
        try {
            $plan = SubscriptionPlan::with(['prices' => function ($query) {
                $query->where('is_active', true)->orderBy('order');
            }])->where('plan_id', $planId)->firstOrFail();

            return response()->json([
                'message' => 'Detalle del plan obtenido exitosamente.',
                'plan' => $plan,
            ], Response::HTTP_OK);
        } catch (Exception $e) {
            return response()->json([
                'error' => 'Error al obtener el detalle del plan: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function createProductWithPrice(ProductWithPriceDTO $dto): JsonResponse
    {
        try {
            $product = Product::create([
                'name' => $dto->productName,
                'description' => $dto->description,
            ]);

            $plan = SubscriptionPlan::create([
                'name' => $dto->productName,
                'description' => $dto->description,
                'stripe_product_id' => $product->id,
                'features' => $dto->features,
                'max_menus' => $dto->maxMenus,
                'max_products' => $dto->maxProducts,
                'is_active' => $dto->isActive,
            ]);

            $prices = [];

            foreach ($dto->prices as $index => $priceData) {
                $stripePrice = Price::create([
                    'unit_amount' => intval($priceData['amount'] * 100),
                    'currency' => $priceData['currency'] ?? 'mxn',
                    'recurring' => ['interval' => $priceData['interval']],
                    'product' => $product->id,
                ]);

                $price = SubscriptionPrice::create([
                    'stripe_price_id' => $stripePrice->id,
                    'price' => $priceData['amount'],
                    'currency' => $priceData['currency'],
                    'interval' => $priceData['interval'],
                    'order' => $priceData['order'] ?? $index,
                    'is_active' => true,
                    'plan_id' => $plan->plan_id,
                ]);

                $prices[] = $price;
            }
            return response()->json([
                'message' => 'Plan y precios creados exitosamente.',
                'plan' => $plan,
                'prices' => $prices,
            ], Response::HTTP_OK);
        } catch (ApiErrorException $e) {
            return response()->json([
                'error' => 'Error con Stripe: ' . $e->getMessage(),
            ], 500);
        } catch (Exception $e) {
            return response()->json([
                'error' => 'Error inesperado: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function updateProductWithPrice(string $planId, ProductWithPriceDTO $dto): JsonResponse
    {
        try {
            $plan = SubscriptionPlan::with('prices')->where('plan_id', $planId)->firstOrFail();

            // Actualizar el producto en Stripe
            \Stripe\Product::update($plan->stripe_product_id, [
                'name' => $dto->productName,
                'description' => $dto->description,
            ]);

            // Actualizar plan local
            $plan->update([
                'name' => $dto->productName,
                'description' => $dto->description,
                'features' => $dto->features,
                'max_menus' => $dto->maxMenus,
                'max_products' => $dto->maxProducts,
                'is_active' => $dto->isActive,
            ]);

            return response()->json([
                'message' => 'Plan se actualizó exitosamente.',
                'plan' => $plan
            ], Response::HTTP_OK);
        } catch (ApiErrorException $e) {
            return response()->json([
                'error' => 'Error con Stripe: ' . $e->getMessage(),
            ], 500);
        } catch (Exception $e) {
            return response()->json([
                'error' => 'Error inesperado: ' . $e->getMessage(),
            ], 500);
        }
    }


    public function deleteProductAndPlan(string $planId): JsonResponse
    {
        try {
            $plan = SubscriptionPlan::where('plan_id', $planId)->firstOrFail();
            if (!$plan) {
                return response()->json(['error' => "Lo sentimos, el plan no existe"], 500);
            }
            Product::update($plan->stripe_product_id, [
                'active' => false
            ]);
            $plan->delete();
            return response()->json([
                'message' => 'El plan se eliminó exitosamente.',
            ], Response::HTTP_OK);
        } catch (ApiErrorException $e) {
            return response()->json([
                'error' => 'Error con Stripe: ' . $e->getMessage(),
            ], 500);
        } catch (Exception $e) {
            return response()->json([
                'error' => 'Error inesperado: ' . $e->getMessage(),
            ], 500);
        }
    }
}