from decimal import Decimal

from django.core.validators import MinValueValidator
from django.db import models


class Material(models.Model):
    """共通資材マスタ"""

    class MaterialType(models.TextChoices):
        FERTILIZER = 'fertilizer', '肥料'
        PESTICIDE = 'pesticide', '農薬'
        SEED = 'seed', '種子'
        SEEDLING = 'seedling', '種苗'
        OTHER = 'other', 'その他'

    class StockUnit(models.TextChoices):
        BAG = 'bag', '袋'
        BOTTLE = 'bottle', '本'
        KG = 'kg', 'kg'
        LITER = 'liter', 'L'
        PIECE = 'piece', '個'

    name = models.CharField(max_length=100, verbose_name='資材名')
    material_type = models.CharField(
        max_length=20,
        choices=MaterialType.choices,
        verbose_name='資材種別',
    )
    maker = models.CharField(
        max_length=100,
        blank=True,
        default='',
        verbose_name='メーカー',
    )
    stock_unit = models.CharField(
        max_length=20,
        choices=StockUnit.choices,
        default=StockUnit.BAG,
        verbose_name='在庫単位',
    )
    is_active = models.BooleanField(default=True, verbose_name='使用中')
    notes = models.TextField(blank=True, default='', verbose_name='備考')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['material_type', 'name']
        constraints = [
            models.UniqueConstraint(
                fields=['material_type', 'name'],
                name='uniq_material_type_name',
            ),
        ]
        verbose_name = '資材'
        verbose_name_plural = '資材'

    def __str__(self):
        return f'{self.get_material_type_display()}: {self.name}'


class FertilizerProfile(models.Model):
    """肥料専用属性"""

    material = models.OneToOneField(
        Material,
        on_delete=models.CASCADE,
        related_name='fertilizer_profile',
    )
    capacity_kg = models.DecimalField(
        max_digits=8,
        decimal_places=3,
        blank=True,
        null=True,
        verbose_name='1袋重量(kg)',
    )
    nitrogen_pct = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        blank=True,
        null=True,
        verbose_name='窒素(%)',
    )
    phosphorus_pct = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        blank=True,
        null=True,
        verbose_name='リン酸(%)',
    )
    potassium_pct = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        blank=True,
        null=True,
        verbose_name='カリ(%)',
    )

    class Meta:
        verbose_name = '肥料詳細'
        verbose_name_plural = '肥料詳細'

    def __str__(self):
        return f'肥料詳細: {self.material.name}'


class PesticideProfile(models.Model):
    """農薬専用属性"""

    material = models.OneToOneField(
        Material,
        on_delete=models.CASCADE,
        related_name='pesticide_profile',
    )
    registration_no = models.CharField(
        max_length=100,
        blank=True,
        default='',
        verbose_name='農薬登録番号',
    )
    formulation = models.CharField(
        max_length=100,
        blank=True,
        default='',
        verbose_name='剤型',
    )
    usage_unit = models.CharField(
        max_length=50,
        blank=True,
        default='',
        verbose_name='使用単位',
    )
    dilution_ratio = models.CharField(
        max_length=100,
        blank=True,
        default='',
        verbose_name='希釈倍率',
    )
    active_ingredient = models.CharField(
        max_length=200,
        blank=True,
        default='',
        verbose_name='有効成分',
    )
    category = models.CharField(
        max_length=100,
        blank=True,
        default='',
        verbose_name='分類',
    )

    class Meta:
        verbose_name = '農薬詳細'
        verbose_name_plural = '農薬詳細'

    def __str__(self):
        return f'農薬詳細: {self.material.name}'


class StockTransaction(models.Model):
    """入出庫履歴"""

    class TransactionType(models.TextChoices):
        PURCHASE = 'purchase', '入庫'
        USE = 'use', '使用'
        RESERVE = 'reserve', '引当'
        ADJUSTMENT_PLUS = 'adjustment_plus', '棚卸増'
        ADJUSTMENT_MINUS = 'adjustment_minus', '棚卸減'
        DISCARD = 'discard', '廃棄'

    INCREASE_TYPES = {
        TransactionType.PURCHASE,
        TransactionType.ADJUSTMENT_PLUS,
    }
    DECREASE_TYPES = {
        TransactionType.USE,
        TransactionType.RESERVE,
        TransactionType.ADJUSTMENT_MINUS,
        TransactionType.DISCARD,
    }

    material = models.ForeignKey(
        Material,
        on_delete=models.PROTECT,
        related_name='stock_transactions',
        verbose_name='資材',
    )
    transaction_type = models.CharField(
        max_length=30,
        choices=TransactionType.choices,
        verbose_name='取引種別',
    )
    quantity = models.DecimalField(
        max_digits=10,
        decimal_places=3,
        validators=[MinValueValidator(Decimal('0.001'))],
        verbose_name='数量',
    )
    occurred_on = models.DateField(verbose_name='発生日')
    note = models.TextField(blank=True, default='', verbose_name='備考')
    fertilization_plan = models.ForeignKey(
        'fertilizer.FertilizationPlan',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='stock_reservations',
        verbose_name='施肥計画',
    )
    spreading_item = models.ForeignKey(
        'fertilizer.SpreadingSessionItem',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='stock_transactions',
        verbose_name='散布実績明細',
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-occurred_on', '-created_at', '-id']
        verbose_name = '入出庫履歴'
        verbose_name_plural = '入出庫履歴'

    def __str__(self):
        return (
            f'{self.material.name} '
            f'{self.get_transaction_type_display()} '
            f'{self.quantity}'
        )
