"""
Paystack API client for the FlashSale platform.
Handles transaction initialization, verification, and webhook signature checks.
"""
import hashlib
import hmac
import logging
import uuid
import requests
from decimal import Decimal
from django.conf import settings

logger = logging.getLogger(__name__)
class PaystackClient:
    """Wrapper around the Paystack REST API."""
    BASE_URL = 'https://api.paystack.co'
    def __init__(self):
        self.secret_key = settings.PAYSTACK_SECRET_KEY
        self.headers = {
            'Authorization': f'Bearer {self.secret_key}',
            'Content-Type': 'application/json',
        }
    def create_subaccount(self, business_name, settlement_bank, account_number, percentage_charge=5.0):
        """
        Create a Paystack Subaccount for seller payout.
        settlement_bank: bank or MoMo code (e.g. MTN, VOD, ATL, 044)
        """
        payload = {
            'business_name': business_name,
            'settlement_bank': settlement_bank,
            'account_number': account_number,
            'percentage_charge': float(percentage_charge),
            'primary_contact_email': 'support@flashsale.com',
        }
        logger.info("Paystack create_subaccount: bank=%s account=%s business=%s",
                    settlement_bank, account_number, business_name)
        try:
            response = requests.post(
                f'{self.BASE_URL}/subaccount',
                json=payload,
                headers=self.headers,
                timeout=30,
            )
            data = response.json()
            logger.info("Paystack create_subaccount response: status_code=%s body=%s",
                        response.status_code, data)
            if data.get('status'):
                return {
                    'success': True,
                    'subaccount_code': data['data']['subaccount_code'],
                    'raw': data['data'],
                }
            logger.warning("Paystack create_subaccount FAILED: %s", data.get('message'))
            return {
                'success': False,
                'message': data.get('message', 'Subaccount creation failed.'),
                'raw': data,
            }
        except Exception as e:
            logger.exception("Paystack create_subaccount exception")
            return {'success': False, 'message': str(e)}
    def update_subaccount(self, subaccount_code, business_name, settlement_bank, account_number, percentage_charge=5.0):
        """Update an existing Paystack Subaccount."""
        payload = {
            'business_name': business_name,
            'settlement_bank': settlement_bank,
            'account_number': account_number,
            'percentage_charge': float(percentage_charge),
            'primary_contact_email': 'support@flashsale.com',
        }
        logger.info("Paystack update_subaccount: code=%s bank=%s account=%s",
                    subaccount_code, settlement_bank, account_number)
        try:
            response = requests.put(
                f'{self.BASE_URL}/subaccount/{subaccount_code}',
                json=payload,
                headers=self.headers,
                timeout=30,
            )
            data = response.json()
            logger.info("Paystack update_subaccount response: status_code=%s body=%s",
                        response.status_code, data)
            if data.get('status'):
                return {'success': True, 'subaccount_code': data['data']['subaccount_code']}
            logger.warning("Paystack update_subaccount FAILED: %s", data.get('message'))
            return {'success': False, 'message': data.get('message', 'Subaccount update failed.')}
        except Exception as e:
            logger.exception("Paystack update_subaccount exception")
            return {'success': False, 'message': str(e)}

    def fetch_subaccount(self, subaccount_code):
        """Fetch a single Paystack Subaccount by code to verify it exists."""
        try:
            response = requests.get(
                f'{self.BASE_URL}/subaccount/{subaccount_code}',
                headers=self.headers,
                timeout=30,
            )
            data = response.json()
            if data.get('status'):
                return {'success': True, 'data': data['data']}
            return {'success': False, 'message': data.get('message', 'Subaccount not found.')}
        except Exception as e:
            return {'success': False, 'message': str(e)}

    def list_subaccounts(self, per_page=50):
        """List all Paystack Subaccounts on this integration."""
        try:
            response = requests.get(
                f'{self.BASE_URL}/subaccount?perPage={per_page}',
                headers=self.headers,
                timeout=30,
            )
            data = response.json()
            if data.get('status'):
                return {'success': True, 'data': data['data'], 'meta': data.get('meta', {})}
            return {'success': False, 'message': data.get('message', 'Failed to list subaccounts.')}
        except Exception as e:
            return {'success': False, 'message': str(e)}
    def initialize_transaction(self, email, amount_ghs, callback_url, metadata=None, subaccount_code=None, is_commission=False):
        """
        Initialize a Paystack transaction.
        Supports automatic split settlement if subaccount_code is provided.
        """
        reference = f"fs_{uuid.uuid4().hex[:16]}"
        amount_pesewas = int(Decimal(str(amount_ghs)) * 100)
        payload = {
            'email': email,
            'amount': amount_pesewas,
            'currency': 'GHS',
            'reference': reference,
            'callback_url': callback_url,
            'metadata': metadata or {},
        }
        if subaccount_code:
            payload['subaccount'] = subaccount_code
            if is_commission:
                # 5% commission retained by platform, 95% routed to seller payout subaccount
                payload['bearer'] = 'subaccount'
            else:
                # Daily rate sale: 100% routed to seller payout subaccount
                payload['transaction_charge'] = 0
        response = requests.post(
            f'{self.BASE_URL}/transaction/initialize',
            json=payload,
            headers=self.headers,
            timeout=30,
        )
        data = response.json()
        if data.get('status'):
            return {
                'success': True,
                'authorization_url': data['data']['authorization_url'],
                'access_code': data['data']['access_code'],
                'reference': data['data']['reference'],
            }
        return {
            'success': False,
            'message': data.get('message', 'Transaction initialization failed.'),
        }
    def verify_transaction(self, reference):
        """
        Server-to-server transaction verification (the ONLY trusted signal).
        Returns: dict with status, amount, metadata.
        """
        response = requests.get(
            f'{self.BASE_URL}/transaction/verify/{reference}',
            headers=self.headers,
            timeout=30,
        )
        data = response.json()
        if data.get('status') and data['data'].get('status') == 'success':
            return {
                'success': True,
                'amount': Decimal(str(data['data']['amount'])) / 100,
                'currency': data['data']['currency'],
                'metadata': data['data'].get('metadata', {}),
                'paid_at': data['data'].get('paid_at'),
                'channel': data['data'].get('channel'),
                'raw': data['data'],
            }
        return {
            'success': False,
            'message': data.get('message', 'Verification failed.'),
            'raw': data.get('data', {}),
        }
    @staticmethod
    def verify_webhook_signature(payload_body, signature_header):
        """
        Verify the x-paystack-signature header (HMAC SHA512) against the
        raw request body. Must be checked BEFORE processing any webhook.
        """
        expected = hmac.new(
            settings.PAYSTACK_SECRET_KEY.encode('utf-8'),
            msg=payload_body,
            digestmod=hashlib.sha512,
        ).hexdigest()
        return hmac.compare_digest(expected, signature_header)
def compute_booking_price(start_date, end_date, pricing_model='daily_rate'):
    """
    Compute the booking fee for a given date range.
    Two models:
      - daily_rate: GHS BOOKING_DAILY_RATE per day
      - commission: GHS 0 upfront, 5% of total sales revenue after sale ends
    """
    delta = (end_date - start_date).days
    num_days = max(delta, 1)
    if pricing_model == 'commission':
        return Decimal('0.00'), num_days
    daily_rate = Decimal(str(settings.BOOKING_DAILY_RATE))
    total = daily_rate * num_days
    return total, num_days