import os
from dotenv import load_dotenv
import aiohttp
from typing import Optional, TypedDict
from datetime import datetime
from payments.pay_provider import BasePayProvider, Invoice
from utils.db import update_payment_status
load_dotenv()


class PayProvider(BasePayProvider):
    def __init__(self, bot_username: str):
        self.token = os.getenv("crypto_bot_token")
        self.api_url = "https://pay.crypt.bot/api"
        self.bot_username = bot_username
        self.name = "💎 Crypto Bot"
        self.callback_data_prefix = "crypto_bot"
        self.description = ""
        self.min_amount = 10

    async def is_available(self) -> bool:
        return self.token is not None
    
    async def _make_request(self, method: str, params: dict = None) -> dict:
        headers = {
            "Crypto-Pay-API-Token": self.token
        }
        
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{self.api_url}/{method}", params=params, headers=headers) as response:
                return await response.json()
    

    async def create_invoice(self, amount: float, payment_id: str, description: str) -> Invoice:
        params = {
            "currency_type": "fiat",
            "fiat": "RUB",
            "accepted_assets": "USDT,USDC",
            "amount": "{:.2f}".format(amount),
            "description": description,
            "paid_btn_name": "callback",
            "paid_btn_url": f"https://t.me/{self.bot_username}",
            "expires_in": 2*60*60 # in seconds
        }
        
        result = await self._make_request("createInvoice", params)
        if not result.get("ok"):
            raise Exception(f"Failed to create invoice: {result.get('error')}")
        
        invoice = Invoice(result["result"]["invoice_id"], result["result"]["amount"], result["result"]["mini_app_invoice_url"])
        return invoice
    
    async def get_invoice(self, invoice_id: int) -> Invoice:
        """Check invoice status by ID"""
        params = {
            "invoice_ids": [invoice_id]
        }
        
        result = await self._make_request("getInvoices", params)
        if not result.get("ok"):
            raise Exception(f"Failed to check invoice: {result.get('error')}")
        
        invoices = result["result"]["items"]
        if not invoices:
            raise Exception(f"Invoice {invoice_id} not found")
        
        return invoices[0]
    
    async def check_invoice(self, invoice_id: int, payment_id: int) -> Invoice:
        invoice = await self.get_invoice(invoice_id)
        if invoice["status"] == "paid":
            await update_payment_status(payment_id, "completed", invoice["paid_at"])
            return True
        return False