"""Server & Client methods for generating and paying L402 offers."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.

# %% auto 0
__all__ = ['db', 'offers', 'payment_requests', 'OfferRow', 'PaymentRequestRow', 'Offer', 'L402Response', 'PaymentServer']

# %% ../nbs/00_core.ipynb 2
import httpx
from datetime import datetime, timezone as dt_timezone, timedelta
from pydantic import BaseModel
from typing import List, Dict
from datetime import datetime, timedelta, timezone
from fastcore.xdg import *
from fastlite import *
import uuid
from .config import _db_path, L402_VERSION


# %% ../nbs/00_core.ipynb 3
db = database(_db_path())


class OfferRow: 
    offer_id:str
    amount:int
    currency:str
    description:str
    payment_methods:list[str]
    title:str
    type:str
    payment_context_token:str
    payment_request_url:str
    version:str
    created_at:str

offers = db.create(OfferRow, name='offers', pk='offer_id')

class PaymentRequestRow: 
    id:int
    offer_id:str
    payment_context_token:str
    payment_method:str
    expires_at:str
    payment_request:dict
    version:str
    created_at:str

payment_requests = db.create(PaymentRequestRow, name='payment_requests', pk='id')



# %% ../nbs/00_core.ipynb 4
class Offer(BaseModel):
    amount: int
    currency: str
    description: str
    offer_id: str
    payment_methods: List[str]
    title: str
    type: str
    
class L402Response(BaseModel):
    offers: List[Offer]
    payment_context_token: str
    payment_request_url: str
    version: str
    
class PaymentServer:
    def __init__(self,
                payment_request_url: str = "http://localhost:8000/payment_request", # endpoint to get payment details for an offer
                lightning_provider = None, # provider to generate lightning invoices
                credit_card_provider = None, # provider to generate credit card payment urls
                onchain_provider = None, # provider to generate onchain payment addresses
                onchain_supported_assets = ['usdc']): # supported assets for onchain payment
        # store_attr()
        self.offers = offers # TODO this is the database
        self.payment_request_url = payment_request_url

        self.lightning_provider = lightning_provider
        self.credit_card_provider = credit_card_provider

        self.onchain_provider = onchain_provider
        self.onchain_supported_assets = onchain_supported_assets

    def create_offers(self, 
                      os: List[Offer]): # List of offers for the L402 Response
        "Create offers and return a L402Response containing the offers, payment_request_url, and a new payment_context_token. Each offer is stored in the database."

        payment_context_token = str(uuid.uuid4())
        version = L402_VERSION
        for offer in os:
            self.offers.insert({
                'offer_id': offer.offer_id,
                'amount': offer.amount,
                'currency': offer.currency,
                'description': offer.description,
                'title': offer.title,
                'type': offer.type,
                'payment_methods': offer.payment_methods,
                'created_at': datetime.now(timezone.utc).isoformat(),
                'payment_context_token': payment_context_token,
                'payment_request_url': self.payment_request_url,
                'version': version,

            })

        return L402Response(
            offers=os,
            payment_context_token=payment_context_token,
            payment_request_url=self.payment_request_url,
            version=version,
        )

# %% ../nbs/00_core.ipynb 6
from fastapi import HTTPException

@patch
def create_payment_request(self: PaymentServer, 
                            offer_id, 
                            payment_context_token,
                            payment_method, 
                            chain = "base-mainnet", # optional, for onchain payment
                            asset = "usdc"): # optional, for onchain payment
    "Create a payment request for an offer. Returns a dict with the payment request details."
    expires_at = (datetime.now(timezone.utc) + timedelta(minutes=35)).isoformat()
    # Example for Lightning payment
    if payment_method == "onchain":
        if self.onchain_provider is None: raise HTTPException(status_code=400, detail="Onchain provider is not set")
        a = self.onchain_provider.create_address()
        if a.network_id != chain: raise HTTPException(status_code=400, detail=f"Requested chain {chain} not supported. Supported chain {a.network_id}")
        if asset not in self.onchain_supported_assets: raise HTTPException(status_code=400, detail=f"Requested asset {asset} not supported by provider {self.onchain_provider}")
        
        pr_data = {
            "expires_at": expires_at,
            "offer_id": offer_id,
            "payment_request": {
                "address": a.address_id,
                "chain": a.network_id,
                "asset": asset
            },
            "version": L402_VERSION
        }

        payment_requests.insert({
            'offer_id': offer_id,
            'payment_context_token': payment_context_token,
            'payment_method': payment_method,
            'expires_at': expires_at,
            'payment_request': pr_data['payment_request'],
            'version': L402_VERSION,
            'created_at': datetime.now(timezone.utc).isoformat()
        })

        return pr_data

    # elif payment_method == "lightning":
    # elif payment_method == "stripe":
    else:
        raise ValueError(f"Payment method {payment_method} is not supported")


