from sqlalchemy import Column, Integer, String, DateTime, Boolean, Float, Text, ForeignKey, Enum, Date
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from src.models.user import db
import enum

class SubscriptionStatus(enum.Enum):
    ACTIVE = "active"
    EXPIRED = "expired"
    CANCELLED = "cancelled"
    TRIAL = "trial"
    PENDING = "pending"

class PaymentStatus(enum.Enum):
    PENDING = "pending"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"
    REFUNDED = "refunded"

class PaymentMethod(enum.Enum):
    CARD = "card"
    KAKAO_PAY = "kakao_pay"
    NAVER_PAY = "naver_pay"
    HECTO_PAY = "hecto_pay"
    PORTONE = "portone"
    TOSS_PAYMENTS = "toss_payments"

class OAuthProvider(enum.Enum):
    KAKAO = "kakao"
    NAVER = "naver"
    GOOGLE = "google"

# 사용자 모델 확장
class UserProfile(db.Model):
    __tablename__ = 'user_profiles'
    
    id = Column(Integer, primary_key=True)
    user_id = Column(String(20), nullable=False)  # User.user_id (논리 FK, DB 제약 없음)
    company_name = Column(String(200))
    business_number = Column(String(20))  # 사업자등록번호
    phone = Column(String(20))
    address = Column(Text)
    department = Column(String(100))
    position = Column(String(100))
    created_at = Column(DateTime, default=func.now())
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
    
    # 관계
    user = relationship(
        'User', back_populates='profile',
        primaryjoin='UserProfile.user_id==User.user_id',
        foreign_keys='UserProfile.user_id',
    )
    oauth_accounts = relationship('OAuthAccount', back_populates='user_profile')

# OAuth 계정 모델
class OAuthAccount(db.Model):
    __tablename__ = 'oauth_accounts'
    
    id = Column(Integer, primary_key=True)
    user_profile_id = Column(Integer, ForeignKey('user_profiles.id'), nullable=False)
    provider = Column(Enum(OAuthProvider), nullable=False)
    provider_user_id = Column(String(100), nullable=False)
    access_token = Column(Text)
    refresh_token = Column(Text)
    expires_at = Column(DateTime)
    created_at = Column(DateTime, default=func.now())
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
    
    # 관계
    user_profile = relationship('UserProfile', back_populates='oauth_accounts')

# 상품 모델
class Product(db.Model):
    __tablename__ = 'products'
    
    id = Column(Integer, primary_key=True)
    name = Column(String(200), nullable=False)
    description = Column(Text)
    price = Column(Integer, nullable=False)  # 원화는 정수로 저장
    currency = Column(String(3), default='KRW')
    billing_cycle = Column(String(20), nullable=False)  # monthly, yearly
    trial_days = Column(Integer, default=15)
    features = Column(Text)  # JSON 형태로 저장
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=func.now())
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
    
    # 관계
    subscriptions = relationship('Subscription', back_populates='product')

# 결제 모델
class Payment(db.Model):
    __tablename__ = 'payments'
    
    id = Column(Integer, primary_key=True)
    user_id = Column(String(20), nullable=False)
    subscription_id = Column(Integer, ForeignKey('subscriptions.id'))
    amount = Column(Float, nullable=False)
    currency = Column(String(3), default='KRW')
    payment_method = Column(Enum(PaymentMethod), nullable=False)
    status = Column(Enum(PaymentStatus), default=PaymentStatus.PENDING)
    
    # PG사 관련 정보
    pg_transaction_id = Column(String(100))  # PG사 거래 ID
    pg_merchant_id = Column(String(100))     # PG사 상점 ID
    pg_response_code = Column(String(10))    # PG사 응답 코드
    pg_response_message = Column(Text)       # PG사 응답 메시지
    
    # 카드 정보 (암호화하여 저장)
    card_last4 = Column(String(4))
    card_brand = Column(String(20))
    billing_key = Column(String(100))  # 자동결제용 빌링키
    
    # 메타데이터
    payment_metadata = Column(Text)  # JSON 형태로 추가 정보 저장
    created_at = Column(DateTime, default=func.now())
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
    
    # 관계
    user = relationship(
        'User', back_populates='payments',
        primaryjoin='Payment.user_id==User.user_id',
        foreign_keys='Payment.user_id',
    )
    subscription = relationship('Subscription', back_populates='payments')

# 구독 모델
class Subscription(db.Model):
    __tablename__ = 'subscriptions'
    
    id = Column(Integer, primary_key=True)
    user_id = Column(String(20), nullable=False)
    product_id = Column(Integer, ForeignKey('products.id'), nullable=False)
    status = Column(Enum(SubscriptionStatus), default=SubscriptionStatus.PENDING)
    
    # 구독 기간
    start_date = Column(DateTime, nullable=False)
    end_date = Column(DateTime, nullable=False)
    trial_end_date = Column(DateTime)  # 무료체험 종료일
    
    # 자동 갱신 설정
    auto_renew = Column(Boolean, default=True)
    next_billing_date = Column(DateTime)
    
    # 취소 정보
    cancelled_at = Column(DateTime)
    cancel_reason = Column(Text)
    
    # 결제 정보
    payment_method = Column(Enum(PaymentMethod), nullable=True)
    payment_id = Column(String(100))  # 결제 ID (토스페이먼츠 payment_key 등)
    amount = Column(Integer)  # 구독 금액 (원화는 정수)
    billing_cycle = Column(String(20))  # 결제 주기 (monthly, yearly)
    prepaid_cycles_remaining = Column(Integer, nullable=False, default=0)  # 선결제된 "월" 개수 (연간 선결제면 12로 시작하여 매월 1씩 감소)
    
    # 크레딧 지급 관련 (next_billing_date는 청구/결제용, next_credit_date는 월별 크레딧 지급용)
    next_credit_date = Column(Date, nullable=True)  # 다음 "크레딧 지급일" (KST 기준 날짜)
    last_credit_date = Column(Date, nullable=True)  # 마지막 지급일 (감사용)
    
    # 메타데이터
    subscription_metadata = Column(Text)  # JSON 형태로 추가 정보 저장
    created_at = Column(DateTime, default=func.now())
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
    
    # 관계
    user = relationship(
        'User', back_populates='subscriptions',
        primaryjoin='Subscription.user_id==User.user_id',
        foreign_keys='Subscription.user_id',
    )
    product = relationship('Product', back_populates='subscriptions')
    payments = relationship('Payment', back_populates='subscription')
    payment_histories = relationship('PaymentHistory', back_populates='subscription')

# 콘텐츠 모델
class Content(db.Model):
    __tablename__ = 'contents'
    
    id = Column(Integer, primary_key=True)
    title = Column(String(200), nullable=False)
    description = Column(Text)
    content_type = Column(String(50))  # video, document, api, etc.
    content_url = Column(Text)
    file_size = Column(Integer)
    duration = Column(Integer)  # 초 단위
    is_premium = Column(Boolean, default=False)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=func.now())
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now())

# 사용자 콘텐츠 접근 권한
class UserContentAccess(db.Model):
    __tablename__ = 'user_content_access'
    
    id = Column(Integer, primary_key=True)
    user_id = Column(String(20), nullable=False)
    content_id = Column(Integer, ForeignKey('contents.id'), nullable=False)
    access_granted_at = Column(DateTime, default=func.now())
    access_expires_at = Column(DateTime)
    is_active = Column(Boolean, default=True)
    
    # 관계
    user = relationship(
        'User', back_populates='content_access',
        primaryjoin='UserContentAccess.user_id==User.user_id',
        foreign_keys='UserContentAccess.user_id',
    )
    content = relationship('Content')

# 웹훅 로그
class WebhookLog(db.Model):
    __tablename__ = 'webhook_logs'
    
    id = Column(Integer, primary_key=True)
    pg_provider = Column(String(50), nullable=False)  # welcomepayments, toss, etc.
    event_type = Column(String(100), nullable=False)
    payload = Column(Text, nullable=False)  # JSON 형태로 저장
    signature = Column(String(200))  # 웹훅 서명
    processed = Column(Boolean, default=False)
    processed_at = Column(DateTime)
    error_message = Column(Text)
    created_at = Column(DateTime, default=func.now())

# 구독 갱신 작업 로그
class SubscriptionRenewalLog(db.Model):
    __tablename__ = 'subscription_renewal_logs'
    
    id = Column(Integer, primary_key=True)
    subscription_id = Column(Integer, ForeignKey('subscriptions.id'), nullable=False)
    renewal_date = Column(DateTime, nullable=False)
    status = Column(String(20), nullable=False)  # success, failed, pending
    amount = Column(Float)
    payment_id = Column(Integer, ForeignKey('payments.id'))
    error_message = Column(Text)
    created_at = Column(DateTime, default=func.now())
    
    # 관계
    subscription = relationship('Subscription')
    payment = relationship('Payment')

