import asyncio
import os
from datetime import datetime, timedelta, timezone
import aiohttp
from typing import Optional, TypedDict
from dotenv import load_dotenv
from payments.pay_provider import BasePayProvider, Invoice
from utils.db import get_payment, update_payment_status

load_dotenv()

class Payment(TypedDict):
	id: int
	amount: float
	status: str
	created_at: str
	paid_at: Optional[str]

class PayProvider(BasePayProvider):
	def __init__(self, bot_username: str):
		self.username = os.getenv("lolz_username")
		self.token = os.getenv("lolz_token")
		self.lolz_user_id = os.getenv("lolz_user_id")
		self.bot_username = bot_username
		self.api_url = "https://api.lzt.market"
		self.check_payments_interval = 10
		self.check_payments_task = None
		self.is_running = False
		self.name = "💚 Lolz"
		self.description = f"<i>Для осуществления оплаты предоставляется срок в 2 часа.</i>"
		self.callback_data_prefix = "lolz" 
		self.min_amount = 10

	async def is_available(self) -> bool:
		result = self.token is not None and self.username is not None and self.lolz_user_id is not None
		if result:
			await self.start_checking()
		return result
	
	def __del__(self):
		if self.is_running:
			self.stop_checking()
	
	async def start_checking(self):
		"""Start periodic payment checking"""
		if not self.is_running:
			self.is_running = True
			self.check_payments_task = asyncio.create_task(self._check_payments_loop())
			print("Started Lolz payment checking loop")
	
	async def stop_checking(self):
		"""Stop periodic payment checking"""
		if self.is_running:
			self.is_running = False
			if self.check_payments_task:
				self.check_payments_task.cancel()
				try:
					await self.check_payments_task
				except asyncio.CancelledError:
					pass
			print("Stopped Lolz payment checking loop")
	
	async def _check_payments_loop(self):
		"""Internal loop for periodic payment checking"""
		while self.is_running:
			try:
				await self.check_payments()
			except Exception as e:
				print(f"Error in payment checking loop: {e}")
			await asyncio.sleep(self.check_payments_interval)
	
	async def _make_request(self, method: str, params: dict = None) -> dict:
		headers = {
			"Authorization": f"Bearer {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: int, payment_id: str, description: str) -> Invoice:
		link = f"https://lzt.market/balance/transfer?username={self.username}&comment={payment_id}&amount={amount}&redirect=https%3A%2F%2Ft.me%2F{self.bot_username}"
		return Invoice(payment_id, amount, link)

	async def check_invoice(self, invoice_id: int, payment_id: int) -> bool:
		payment = await get_payment(payment_id)
		if payment is None:
			return False
		return payment.status == "completed"
	
	async def check_payments(self, check_minutes: int = 240) -> Optional[Payment]:
		"""Check for payment with specific amount in last N minutes"""
		# Calculate time range
		end_date = datetime.now(timezone.utc)
		start_date = end_date - timedelta(minutes=check_minutes)
		
		# Format dates for API
		start_str = start_date.strftime("%Y-%m-%dT%H:%M:%S+00:00")
		end_str = end_date.strftime("%Y-%m-%dT%H:%M:%S+00:00")
		
		page = 1
		while True:
			params = {
				"type": "receiving_money",
				"page": page,
				"startDate": start_str,
				"endDate": end_str
			}
			
			try:
				result = await self._make_request(f"user/{self.lolz_user_id}/payments", params)
				
				if not result.get("payments"):
					break
				
				# Check each payment
				for payment_id, payment_data in result["payments"].items():
					if (payment_data["is_finished"] == 1 and 
						payment_data["is_hold"] == 0):
						try:
							# Get comment as payment_id
							comment = payment_data["data"]["comment"]
							payment_id = comment
							
							payment_db = await get_payment(payment_id)
							if payment_db is None:
								continue
							
							if payment_db.status == "pending":
								# Check amount
								if payment_db.amount != float(payment_data["incoming_sum"]):
									continue
								
								# Convert timestamp to datetime
								paid_at = datetime.fromtimestamp(payment_data["operation_date"], tz=timezone.utc)
								# Update payment status
								await update_payment_status(payment_id, "completed", paid_at)
								print(f"Payment {payment_id} marked as completed")
						except (ValueError, KeyError) as e:
							print(f"Error processing payment {payment_id}: {e}")
							continue
				
				if not result.get("hasNextPage", False):
					break
					
				page += 1
				
			except Exception as e:
				print(f"Error checking Lolz payment: {e}")
				break
		
		return None