#!/usr/bin/env python3
"""
기간 연장형 구독 모델 구현
요구사항에 맞게 구독 로직을 정리합니다.
"""

import os
from datetime import datetime, timedelta
from flask import Blueprint, request, jsonify, session, current_app
from src.models.subscription import Subscription, SubscriptionStatus, PaymentMethod
from src.models.payment import PaymentHistory
from src.models.user import User
from src.models.db import db
from src.utils.user_ref import parse_mlink_order_user_id, resolve_user_ref
import logging
import requests
import uuid

logger = logging.getLogger(__name__)

TOSS_CONFIG = {
    'api_key': os.environ.get('TOSS_API_KEY'),
    'base_url': 'https://pay.toss.im/api/v2/payments',
    'refund_url': 'https://pay.toss.im/api/v2/refunds',  # 복수형으로 통일
    'status_url': 'https://pay.toss.im/api/v2/status',
    'execute_url': 'https://pay.toss.im/api/v2/execute'
}

def calculate_end_date(billing_cycle):
    """결제 주기에 따른 종료일 계산 (오늘 제외)"""
    now = datetime.now()
    if billing_cycle == 'yearly':
        return now + timedelta(days=364)  # 365일 (오늘 제외)
    else:  # monthly
        return now + timedelta(days=29)   # 30일 (오늘 제외)

def calculate_refund_amount_for_payment(payment_history):
    """기간 연장형 모델 - 특정 결제의 환불 금액 계산"""
    try:
        if not payment_history.subscription_start_date or not payment_history.subscription_end_date:
            return 0
            
        now = datetime.now()
        start_date = payment_history.subscription_start_date
        end_date = payment_history.subscription_end_date
        
        # 결제 기간이 아직 시작되지 않은 경우 (전액 환불)
        if now < start_date:
            return payment_history.amount
            
        # 결제 기간이 이미 만료된 경우 (환불 불가)
        if now >= end_date:
            return 0
            
        # 사용하지 않은 기간 계산
        remaining_days = (end_date - now).days
        total_days = (end_date - start_date).days
        
        if total_days <= 0:
            return 0
            
        # 비례 환불 계산
        refund_ratio = remaining_days / total_days
        refund_amount = int(payment_history.amount * refund_ratio)
        
        logger.info(f'결제 {payment_history.id} 환불 계산:')
        logger.info(f'  - 결제 금액: {payment_history.amount}원')
        logger.info(f'  - 구독 기간: {start_date} ~ {end_date}')
        logger.info(f'  - 남은 일수: {remaining_days}일 / 총 {total_days}일')
        logger.info(f'  - 환불 비율: {refund_ratio:.2%}')
        logger.info(f'  - 환불 금액: {refund_amount}원')
        
        return refund_amount
        
    except Exception as e:
        logger.error(f'환불 금액 계산 실패: {str(e)}')
        return 0

def create_subscription_extension_model(payment_result):
    """기간 연장형 구독 모델 - 구독 생성/연장"""
    try:
        logger.info(f'기간 연장형 구독 모델 - 결제 처리 시작: {payment_result}')
        
        # 결제 정보에서 필요한 데이터 추출
        payment_key = payment_result.get('paymentKey')
        order_id = payment_result.get('orderId')
        amount = payment_result.get('amount')
        status = payment_result.get('status', 'DONE')
        
        # 주문 ID에서 업무 user_id 추출
        user_id = parse_mlink_order_user_id(order_id) or '1'
        
        # 주문 ID에서 상품 정보 추출
        product_id = 77  # Basic 상품 ID
        
        # 주문 ID에서 billing_cycle 정보 추출
        billing_cycle = 'monthly'  # 기본값
        if order_id and 'mlink_' in order_id:
            try:
                parts = order_id.split('_')
                if len(parts) >= 3:
                    last_three = parts[-3:]
                    billing_cycle_part = last_three[1]
                    if billing_cycle_part in ['monthly', 'yearly']:
                        billing_cycle = billing_cycle_part
            except Exception as e:
                logger.error(f'billing_cycle 추출 실패: {str(e)}')
                billing_cycle = 'monthly'
        
        # 기존 활성 구독 확인
        existing_subscription = Subscription.query.filter_by(
            user_id=user_id, 
            status=SubscriptionStatus.ACTIVE
        ).first()
        
        if existing_subscription:
            # 기간 중 추가 결제 (연장)
            logger.info(f'기간 중 추가 결제 - 구독 연장: {existing_subscription.id}')
            logger.info(f'기존 종료일: {existing_subscription.end_date}')
            
            # 현재 종료일을 기준으로 추가 기간 연장
            current_end_date = existing_subscription.end_date
            additional_period = calculate_end_date(billing_cycle) - datetime.now()
            
            # 기존 종료일에서 추가 기간만큼 연장
            new_end_date = current_end_date + additional_period
            
            # subscriptions 테이블 업데이트 (만료일만 갱신)
            existing_subscription.end_date = new_end_date
            existing_subscription.next_billing_date = new_end_date
            existing_subscription.updated_at = datetime.now()
            
            logger.info(f'구독 연장 완료: {existing_subscription.id}')
            logger.info(f'새 종료일: {new_end_date}')
            logger.info(f'연장 기간: {additional_period.days}일')
            
            db.session.commit()
            subscription = existing_subscription
            
        else:
            # 첫 결제 (구독 시작)
            logger.info(f'첫 결제 - 새 구독 생성')
            
            # 새 구독 생성
            end_date = calculate_end_date(billing_cycle)
            subscription = Subscription(
                user_id=user_id,
                product_id=product_id,
                status=SubscriptionStatus.ACTIVE,
                payment_method=PaymentMethod.TOSS_PAYMENTS,
                payment_id=payment_key,
                amount=float(amount),
                billing_cycle=str(billing_cycle),
                start_date=datetime.now(),
                end_date=end_date,
                next_billing_date=end_date,
                created_at=datetime.now(),
                updated_at=datetime.now()
            )

            db.session.add(subscription)
            db.session.commit()
            
            # 첫 결제 시 사용자 권한 업데이트 (role_pro)
            try:
                user = resolve_user_ref(user_id)
                if user:
                    user.role = 'role_pro'
                    db.session.commit()
                    logger.info(f'사용자 권한 업데이트 완료: user_id={user_id}, role=role_pro')
                else:
                    logger.warning(f'사용자를 찾을 수 없음: user_id={user_id}')
            except Exception as e:
                logger.error(f'사용자 권한 업데이트 실패: {str(e)}')
        
        # PaymentHistory에 새 row 추가 (기간 연장형 모델)
        try:
            # 구독 기간 계산
            end_date = calculate_end_date(billing_cycle)
            subscription_days = (end_date - datetime.now()).days
            
            # 상품 정보 조회
            from src.models.subscription import Product
            product = Product.query.get(product_id)
            
            # 기간 연장형 모델: 모든 결제는 새로운 PaymentHistory row로 추가
            payment_history = PaymentHistory(
                user_id=user_id,
                subscription_id=subscription.id,
                payment_key=payment_key,
                order_id=order_id,
                amount=amount,
                status='completed',
                payment_method='toss_payments',
                product_id=product_id,
                product_name=product.name if product else 'Unknown Product',
                product_price=product.price if product else amount,
                billing_cycle=billing_cycle,
                subscription_days=subscription_days,
                subscription_start_date=datetime.now(),
                subscription_end_date=end_date,
                created_at=datetime.now()
            )
            db.session.add(payment_history)
            db.session.commit()
            
            logger.info(f'PaymentHistory 새 row 추가 완료: {payment_history.id}')
            logger.info(f'  - payToken: {payment_key}')
            logger.info(f'  - 구독일수: {subscription_days}일')
            logger.info(f'  - 구독 시작일: {datetime.now()}')
            logger.info(f'  - 구독 종료일: {end_date}')
                
        except Exception as e:
            logger.error(f'결제 이력 처리 실패: {str(e)}')

        logger.info(f'기간 연장형 구독 모델 - 결제 처리 완료: {subscription.id}')
        return subscription
        
    except Exception as e:
        logger.error(f'기간 연장형 구독 모델 - 결제 처리 실패: {str(e)}')
        raise

def cancel_subscription_extension_model():
    """기간 연장형 구독 모델 - 구독 취소"""
    try:
        user_id = session.get('user_id')
        if not user_id:
            return jsonify({'error': '로그인이 필요합니다.'}), 401

        subscription = Subscription.query.filter_by(
            user_id=user_id,
            status=SubscriptionStatus.ACTIVE
        ).first()

        if not subscription:
            return jsonify({'error': '활성 구독이 없습니다.'}), 404

        logger.info(f'기간 연장형 구독 취소 시작: subscription_id={subscription.id}')
        
        # 최근 결제 조회 (가장 최근 완료된 결제)
        latest_payment = PaymentHistory.query.filter_by(
            subscription_id=subscription.id,
            status='completed'
        ).order_by(PaymentHistory.created_at.desc()).first()
        
        if not latest_payment:
            logger.warning(f'구독 {subscription.id}의 완료된 결제를 찾을 수 없음')
            return jsonify({'error': '환불할 결제를 찾을 수 없습니다.'}), 404
        
        logger.info(f'최근 결제 발견: payment_key={latest_payment.payment_key}, amount={latest_payment.amount}')
        
        # 최근 결제의 환불 금액 계산
        refund_amount = calculate_refund_amount_for_payment(latest_payment)
        logger.info(f'최근 결제 환불 금액: {refund_amount}원')
        
        refund_result = {'success': False, 'error': '환불 처리 실패'}
        
        if refund_amount > 0:
            # 토스페이먼츠 환불 API 호출
            try:
                refund_no = f'refund_{uuid.uuid4().hex[:16]}'
                
                # 환불 금액 계산 (부가세 포함)
                amount_taxable = int(refund_amount / 1.1)
                amount_vat = refund_amount - amount_taxable
                
                refund_data = {
                    'apiKey': os.environ.get('TOSS_API_KEY'),
                    'payToken': latest_payment.payment_key,
                    'refundNo': refund_no,
                    'amount': refund_amount,
                    'amountTaxable': amount_taxable,
                    'amountTaxFree': 0,
                    'amountVat': amount_vat,
                    'amountServiceFee': 0,
                    'reason': '구입 취소 환불'
                }
                
                logger.info(f'토스페이먼츠 환불 요청: {refund_data}')
                
                refund_response = requests.post(
                    TOSS_CONFIG['refund_url'],
                    headers={'Content-Type': 'application/json'},
                    json=refund_data,
                    timeout=30
                )
                
                if refund_response.status_code == 200:
                    refund_result_data = refund_response.json()
                    logger.info(f'토스페이먼츠 환불 성공: {refund_result_data}')
                    
                    # 최근 결제 상태를 'refunded'로 변경
                    latest_payment.status = 'refunded'
                    latest_payment.description = f'환불 완료 - {refund_no}'
                    db.session.commit()
                    
                    # 구독 기간 회수 (subscription_days만큼 되돌리기)
                    if latest_payment.subscription_days:
                        subscription.end_date = subscription.end_date - timedelta(days=latest_payment.subscription_days)
                        subscription.next_billing_date = subscription.end_date
                        subscription.updated_at = datetime.now()
                        db.session.commit()
                        
                        logger.info(f'구독 기간 회수 완료: {latest_payment.subscription_days}일 차감')
                        logger.info(f'새 종료일: {subscription.end_date}')
                    
                    # 만료 여부 확인
                    if subscription.end_date <= datetime.now():
                        subscription.status = SubscriptionStatus.CANCELLED
                        subscription.next_billing_date = None
                        db.session.commit()
                        
                        # 권한 회수
                        try:
                            user = resolve_user_ref(subscription.user_id)
                            if user:
                                user.role = 'role_free'
                                db.session.commit()
                                logger.info(f'사용자 권한 회수 완료: user_id={subscription.user_id}, role=role_free')
                        except Exception as e:
                            logger.error(f'사용자 권한 회수 실패: {str(e)}')
                        
                        logger.info(f'구독 만료로 인한 취소 처리 완료')
                    
                    refund_result = {
                        'success': True,
                        'total_amount': refund_amount,
                        'amount_taxable': amount_taxable,
                        'amount_vat': amount_vat,
                        'refund_no': refund_no,
                        'subscription_days_recovered': latest_payment.subscription_days
                    }
                    
                else:
                    logger.error(f'토스페이먼츠 환불 실패: {refund_response.status_code} - {refund_response.text}')
                    refund_result = {
                        'success': False,
                        'error': f'환불 API 실패: {refund_response.status_code}',
                        'refund_no': refund_no
                    }
                    
            except Exception as e:
                logger.error(f'환불 처리 중 오류: {str(e)}')
                refund_result = {
                    'success': False,
                    'error': str(e)
                }
        else:
            logger.info('환불 가능한 금액이 없습니다.')
            refund_result = {
                'success': False,
                'error': '환불 가능한 금액이 없습니다.'
            }
        
        logger.info(f'기간 연장형 구독 취소 완료: {refund_result}')
        
        return jsonify({
            'success': True,
            'message': '구독이 성공적으로 취소되었습니다.',
            'refund': refund_result
        }), 200
        
    except Exception as e:
        db.session.rollback()
        logger.exception("기간 연장형 구독 취소 실패")
        return jsonify({'error': str(e)}), 500
