from django.contrib.auth.decorators import login_required
from accounts.utils import safe_form, sanitize_workbook, parse_int
from django.shortcuts import render, redirect, get_object_or_404
from django.shortcuts import render, redirect
from django.core.paginator import Paginator
from django.http import HttpResponse
from django.db import transaction

from openpyxl import Workbook

from .models import Asset, AssetCategory, AssetSpecification
from facilities.models import Facility
from activities.models import Activity
from maintenance.models import Maintenance

@login_required(login_url='login')
def asset_list(request):
    assets = Asset.objects.select_related(
        'category',
        'location'
    ).all()

    categories = AssetCategory.objects.filter(
        is_active=True
    )

    facilities = Facility.objects.filter(
        status='ACTIVE'
    )

    search = request.GET.get(
        'search',
        ''
    ).strip()

    category_id = request.GET.get(
        'category',
        ''
    ).strip()
    category_id = category_id if category_id.isdigit() else ''

    status = request.GET.get(
        'status',
        ''
    ).strip()

    location_id = request.GET.get(
        'location',
        ''
    ).strip()
    location_id = location_id if location_id.isdigit() else ''

    if search:
        assets = assets.filter(
            asset_code__icontains=search
        ) | assets.filter(
            name__icontains=search
        ) | assets.filter(
            brand__icontains=search
        ) | assets.filter(
            model__icontains=search
        ) | assets.filter(
            serial_number__icontains=search
        )

    if category_id:
        assets = assets.filter(
            category_id=category_id
        )

    if status:
        assets = assets.filter(
            status=status
        )

    if location_id:
        assets = assets.filter(
            location_id=location_id
        )

    # تعداد نتایج بعد از اعمال تمام فیلترها
    asset_count = assets.count()

    paginator = Paginator(
    assets,
    10
)

    page_number = request.GET.get(
    'page'
)

    page_obj = paginator.get_page(
    page_number
)

    context = {
        'assets': assets,
        'categories': categories,
        'facilities': facilities,
        'status_choices': Asset.STATUS_CHOICES,
        'search': search,
        'category_id': category_id,
        'status': status,
        'location_id': location_id,
        'asset_count': asset_count,
        'page_obj': page_obj,
    }

    return render(
        request,
        'inventory/asset_list.html',
        context
    )

@login_required(login_url='login')
@safe_form
def asset_create(request):

    categories = AssetCategory.objects.filter(
        is_active=True
    )

    facilities = Facility.objects.filter(
        status='ACTIVE'
    )

    # دریافت مکان از URL
    location_id = request.GET.get(
        'location',
        ''
    ).strip()
    location_id = location_id if location_id.isdigit() else ''

    # پیدا کردن مکان انتخاب‌شده
    selected_location = None

    if location_id:
        selected_location = Facility.objects.filter(
            pk=location_id,
            status='ACTIVE'
        ).first()

    if request.method == 'POST':

        category_id = request.POST.get(
            'category'
        )

        name = request.POST.get(
            'name',
            ''
        ).strip()

        brand = request.POST.get(
            'brand',
            ''
        ).strip()

        model = request.POST.get(
            'model',
            ''
        ).strip()

        serial_number = request.POST.get(
            'serial_number',
            ''
        ).strip()

        quantity = request.POST.get(
            'quantity',
            '1'
        ).strip()

        location_id = request.POST.get(
            'location'
        )

        condition = request.POST.get(
            'condition',
            'GOOD'
        )

        status = request.POST.get(
            'status',
            'ACTIVE'
        )

        purchase_date = request.POST.get(
            'purchase_date'
        ) or None

        purchase_price = request.POST.get(
            'purchase_price'
        ) or None

        warranty_expiry = request.POST.get(
            'warranty_expiry'
        ) or None

        description = request.POST.get(
            'description',
            ''
        ).strip()

        # ذخیره تجهیز و مشخصات تخنیکی
        with transaction.atomic():

            asset = Asset.objects.create(
                category_id=category_id,
                name=name,
                brand=brand,
                model=model,
                serial_number=serial_number,
                quantity=int(quantity) if quantity else 1,
                location_id=location_id,
                condition=condition,
                status=status,
                purchase_date=purchase_date,
                purchase_price=purchase_price,
                warranty_expiry=warranty_expiry,
                description=description,
            )

            # دریافت مشخصات تخنیکی
            spec_keys = request.POST.getlist(
                'spec_key[]'
            )

            spec_values = request.POST.getlist(
                'spec_value[]'
            )

            # ذخیره مشخصات تخنیکی
            for key, value in zip(
                spec_keys,
                spec_values
            ):

                key = key.strip()
                value = value.strip()

                if key and value:
                    AssetSpecification.objects.create(
                        asset=asset,
                        key=key,
                        value=value,
                    )

        # برگشت به صفحه مکان
        return redirect(
            'facility_detail',
            pk=location_id
        )

    context = {
        'categories': categories,
        'facilities': facilities,
        'condition_choices': Asset.CONDITION_CHOICES,
        'status_choices': Asset.STATUS_CHOICES,
        'selected_location': selected_location,
    }

    return render(
        request,
        'inventory/asset_form.html',
        context
    )

@login_required(login_url='login')
def asset_detail(request, pk):

    asset = Asset.objects.select_related(
        'category',
        'location'
    ).get(pk=pk)

    activities = Activity.objects.filter(
        asset=asset
    ).order_by(
        '-date'
    )

    maintenances = Maintenance.objects.filter(
        asset=asset
    ).order_by(
        '-report_date'
    )

    return render(
        request,
        'inventory/asset_detail.html',
        {
            'asset': asset,
            'activities': activities,
            'maintenances': maintenances,
        }
    )

@login_required(login_url='login')
@safe_form
def asset_update(request, pk):

    asset = get_object_or_404(Asset, 
        pk=pk
    )

    categories = AssetCategory.objects.filter(
        is_active=True
    )

    facilities = Facility.objects.filter(
        status='ACTIVE'
    )

    # مکان فعلی تجهیز
    selected_location = asset.location

    if request.method == 'POST':

        category_id = request.POST.get(
            'category'
        )

        asset_code = request.POST.get(
            'asset_code',
            ''
        ).strip()

        name = request.POST.get(
            'name',
            ''
        ).strip()

        brand = request.POST.get(
            'brand',
            ''
        ).strip()

        model = request.POST.get(
            'model',
            ''
        ).strip()

        serial_number = request.POST.get(
            'serial_number',
            ''
        ).strip()

        quantity = request.POST.get(
            'quantity',
            '1'
        ).strip()

        location_id = request.POST.get(
            'location'
        )

        condition = request.POST.get(
            'condition',
            'GOOD'
        )

        status = request.POST.get(
            'status',
            'ACTIVE'
        )

        purchase_date = (
            request.POST.get(
                'purchase_date'
            )
            or None
        )

        purchase_price = (
            request.POST.get(
                'purchase_price'
            )
            or None
        )

        warranty_expiry = (
            request.POST.get(
                'warranty_expiry'
            )
            or None
        )

        description = request.POST.get(
            'description',
            ''
        ).strip()


        # بررسی تکراری بودن کد تجهیز
        # به جز خود تجهیز فعلی

        if Asset.objects.filter(
            asset_code=asset_code
        ).exclude(
            pk=asset.pk
        ).exists():

            context = {
                'asset': asset,
                'categories': categories,
                'facilities': facilities,
                'condition_choices': Asset.CONDITION_CHOICES,
                'status_choices': Asset.STATUS_CHOICES,
                'selected_location': selected_location,
                'error': (
                    'این کد تجهیز قبلاً برای یک تجهیز دیگر '
                    'ثبت شده است. لطفاً کد دیگری وارد کنید.'
                ),
                'form_data': request.POST,
            }

            return render(
                request,
                'inventory/asset_form.html',
                context
            )


        asset.category_id = category_id

        asset.asset_code = asset_code

        asset.name = name

        asset.brand = brand

        asset.model = model

        asset.serial_number = serial_number

        asset.quantity = (
            int(quantity)
            if quantity
            else 1
        )

        asset.location_id = location_id

        asset.condition = condition

        asset.status = status

        asset.purchase_date = purchase_date

        asset.purchase_price = purchase_price

        asset.warranty_expiry = warranty_expiry

        asset.description = description

        asset.save()


        return redirect(
            'asset_detail',
            pk=asset.pk
        )


    context = {
        'asset': asset,
        'categories': categories,
        'facilities': facilities,
        'condition_choices': Asset.CONDITION_CHOICES,
        'status_choices': Asset.STATUS_CHOICES,
        'selected_location': selected_location,
    }


    return render(
        request,
        'inventory/asset_form.html',
        context
    )
@login_required(login_url='login')
def asset_delete(request, pk):
    asset = get_object_or_404(Asset, pk=pk)

    if request.method == 'POST':
        asset.delete()
        return redirect('asset_list')

    return render(
        request,
        'inventory/asset_confirm_delete.html',
        {
            'asset': asset,
        }
    )

@login_required(login_url='login')
@safe_form
def asset_specification_create(request, asset_id):
    asset = get_object_or_404(Asset, pk=asset_id)

    error_message = None

    if request.method == 'POST':
        key = request.POST.get('key', '').strip()
        value = request.POST.get('value', '').strip()

        if AssetSpecification.objects.filter(
            asset=asset,
            key__iexact=key
        ).exists():
            error_message = (
                'این مشخصه قبلاً برای این تجهیز ثبت شده است.'
            )
        else:
            AssetSpecification.objects.create(
                asset=asset,
                key=key,
                value=value,
            )

            return redirect(
                'asset_detail',
                pk=asset.pk
            )

    return render(
        request,
        'inventory/asset_specification_form.html',
        {
            'asset': asset,
            'error_message': error_message,
        }
    )

@login_required(login_url='login')
@safe_form
def asset_specification_update(request, pk):
    specification = get_object_or_404(AssetSpecification, pk=pk)
    asset = specification.asset

    error_message = None

    if request.method == 'POST':
        key = request.POST.get('key', '').strip()
        value = request.POST.get('value', '').strip()

        duplicate_exists = AssetSpecification.objects.filter(
            asset=asset,
            key__iexact=key
        ).exclude(
            pk=specification.pk
        ).exists()

        if duplicate_exists:
            error_message = (
                'این مشخصه قبلاً برای این تجهیز ثبت شده است.'
            )
        else:
            specification.key = key
            specification.value = value
            specification.save()

            return redirect(
                'asset_detail',
                pk=asset.pk
            )

    return render(
        request,
        'inventory/asset_specification_form.html',
        {
            'asset': asset,
            'specification': specification,
            'error_message': error_message,
        }
    )
@login_required(login_url='login')
def asset_specification_delete(request, pk):
    specification = get_object_or_404(AssetSpecification, pk=pk)
    asset = specification.asset

    if request.method == 'POST':
        specification.delete()

        return redirect(
            'asset_detail',
            pk=asset.pk
        )

    return render(
        request,
        'inventory/asset_specification_confirm_delete.html',
        {
            'specification': specification,
            'asset': asset,
        }
    ) 

@login_required(login_url='login')
def asset_print(request, pk):
    asset = Asset.objects.select_related(
        'category',
        'location'
    ).get(pk=pk)

    activities = Activity.objects.filter(
        asset=asset
    ).order_by(
        '-date'
    )

    maintenances = Maintenance.objects.filter(
        asset=asset
    ).order_by(
        '-report_date'
    )

    return render(
        request,
        'inventory/asset_print.html',
        {
            'asset': asset,
            'activities': activities,
            'maintenances': maintenances,
        }
    )

@login_required(login_url='login')
def category_list(request):

    categories = AssetCategory.objects.all().prefetch_related('assets')

    return render(
        request,
        'inventory/category_list.html',
        {
            'categories': categories,
        }
    )
@login_required(login_url='login')
@safe_form
def category_create(request):

    if request.method == 'POST':

        name = request.POST.get('name', '').strip()
        code = request.POST.get('code', '').strip()
        description = request.POST.get('description', '').strip()

        # بررسی تکراری بودن کد
        if AssetCategory.objects.filter(code=code).exists():

            return render(
                request,
                'inventory/category_form.html',
                {
                    'error': 'این کد دسته قبلاً ثبت شده است. لطفاً کد دیگری وارد کنید.',
                    'form_name': name,
                    'form_code': code,
                    'form_description': description,
                }
            )

        AssetCategory.objects.create(
            name=name,
            code=code,
            description=description,
            is_active=True,
        )

        return redirect('category_list')

    return render(
        request,
        'inventory/category_form.html'
    )
@login_required(login_url='login')
def category_detail(request, pk):

    category = get_object_or_404(AssetCategory, pk=pk)

    return render(
        request,
        'inventory/category_detail.html',
        {
            'category': category,
        }
    )

@login_required(login_url='login')
@safe_form
def category_update(request, pk):

    category = get_object_or_404(AssetCategory, pk=pk)

    if request.method == 'POST':

        name = request.POST.get('name', '').strip()
        code = request.POST.get('code', '').strip()
        description = request.POST.get('description', '').strip()
        is_active = request.POST.get('is_active') == 'on'

        # بررسی تکراری بودن کد برای دسته دیگری
        if AssetCategory.objects.filter(code=code).exclude(pk=category.pk).exists():

            return render(
                request,
                'inventory/category_form.html',
                {
                    'category': category,
                    'error': 'این کد دسته قبلاً برای یک دسته دیگر ثبت شده است. لطفاً کد دیگری وارد کنید.',
                }
            )

        category.name = name
        category.code = code
        category.description = description
        category.is_active = is_active

        category.save()

        return redirect('category_detail', pk=category.pk)

    return render(
        request,
        'inventory/category_form.html',
        {
            'category': category,
        }
    )

@login_required(login_url='login')
def category_delete(request, pk):

    category = get_object_or_404(AssetCategory, pk=pk)

    if request.method == 'POST':
        category.delete()
        return redirect('category_list')

    return render(
        request,
        'inventory/category_confirm_delete.html',
        {
            'category': category,
        }
    )

@login_required(login_url='login')
def asset_report(request):

    assets = Asset.objects.select_related(
        'category',
        'location'
    ).all()

    categories = AssetCategory.objects.filter(
        is_active=True
    )

    facilities = Facility.objects.filter(
        status='ACTIVE'
    )

    # دریافت فیلترها

    category_id = request.GET.get(
        'category',
        ''
    ).strip()
    category_id = category_id if category_id.isdigit() else ''

    status = request.GET.get(
        'status',
        ''
    ).strip()

    location_id = request.GET.get(
        'location',
        ''
    ).strip()
    location_id = location_id if location_id.isdigit() else ''


    # فیلتر بر اساس دسته

    if category_id:

        assets = assets.filter(
            category_id=category_id
        )


    # فیلتر بر اساس وضعیت

    if status:

        assets = assets.filter(
            status=status
        )


    # فیلتر بر اساس مکان

    if location_id:

        assets = assets.filter(
            location_id=location_id
        )


    context = {

        'assets': assets,

        'asset_count': assets.count(),

        'categories': categories,

        'facilities': facilities,

        'status_choices': Asset.STATUS_CHOICES,

        'category_id': category_id,

        'status': status,

        'location_id': location_id,

    }


    return render(
        request,
        'inventory/asset_report.html',
        context
    )

@login_required(login_url='login')
def asset_report_print(request):

    assets = Asset.objects.select_related(
        'category',
        'location'
    ).all()

    category_id = request.GET.get(
        'category',
        ''
    ).strip()
    category_id = category_id if category_id.isdigit() else ''

    status = request.GET.get(
        'status',
        ''
    ).strip()

    location_id = request.GET.get(
        'location',
        ''
    ).strip()
    location_id = location_id if location_id.isdigit() else ''


    # فیلتر دسته

    if category_id:

        assets = assets.filter(
            category_id=category_id
        )


    # فیلتر وضعیت

    if status:

        assets = assets.filter(
            status=status
        )


    # فیلتر مکان

    if location_id:

        assets = assets.filter(
            location_id=location_id
        )


    context = {

        'assets': assets,

        'asset_count': assets.count(),

        'category_id': category_id,

        'status': status,

        'location_id': location_id,

    }


    return render(
        request,
        'inventory/asset_report_print.html',
        context
    )

@login_required(login_url='login')
def asset_report_excel(request):

    from openpyxl import Workbook
    from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
    from openpyxl.utils import get_column_letter
    from openpyxl.worksheet.table import Table, TableStyleInfo

    assets = Asset.objects.select_related(
        'category',
        'location'
    ).all()


    # =========================================================
    # دریافت فیلترها
    # =========================================================

    category_id = request.GET.get(
        'category',
        ''
    ).strip()
    category_id = category_id if category_id.isdigit() else ''

    status = request.GET.get(
        'status',
        ''
    ).strip()

    location_id = request.GET.get(
        'location',
        ''
    ).strip()
    location_id = location_id if location_id.isdigit() else ''


    # =========================================================
    # اعمال فیلترها
    # =========================================================

    if category_id:

        assets = assets.filter(
            category_id=category_id
        )


    if status:

        assets = assets.filter(
            status=status
        )


    if location_id:

        assets = assets.filter(
            location_id=location_id
        )


    # =========================================================
    # ایجاد Workbook
    # =========================================================

    workbook = Workbook()

    worksheet = workbook.active

    worksheet.title = 'گزارش تجهیزات'


    # =========================================================
    # تنظیم راست به چپ
    # =========================================================

    worksheet.sheet_view.rightToLeft = True


    # =========================================================
    # رنگ‌ها و Styleها
    # =========================================================

    dark_blue = '17365D'

    light_blue = 'D9EAF7'

    white = 'FFFFFF'

    border_color = 'B7B7B7'


    thin_border = Border(

        left=Side(
            style='thin',
            color=border_color
        ),

        right=Side(
            style='thin',
            color=border_color
        ),

        top=Side(
            style='thin',
            color=border_color
        ),

        bottom=Side(
            style='thin',
            color=border_color
        )

    )


    # =========================================================
    # عنوان گزارش
    # =========================================================

    worksheet.merge_cells(
        'A1:J1'
    )

    worksheet['A1'] = (
        'امارت اسلامی افغانستان'
    )

    worksheet['A1'].font = Font(
        bold=True,
        size=16
    )

    worksheet['A1'].alignment = Alignment(
        horizontal='center',
        vertical='center'
    )


    worksheet.merge_cells(
        'A2:J2'
    )

    worksheet['A2'] = (
        'وزارت تحصیلات عالی'
    )

    worksheet['A2'].font = Font(
        bold=True,
        size=14
    )

    worksheet['A2'].alignment = Alignment(
        horizontal='center',
        vertical='center'
    )


    worksheet.merge_cells(
        'A3:J3'
    )

    worksheet['A3'] = (
        'پوهنتون طبی چراغ'
    )

    worksheet['A3'].font = Font(
        bold=True,
        size=15
    )

    worksheet['A3'].alignment = Alignment(
        horizontal='center',
        vertical='center'
    )


    worksheet.merge_cells(
        'A4:J4'
    )

    worksheet['A4'] = (
        'آمریت تکنالوژی معلوماتی'
    )

    worksheet['A4'].font = Font(
        bold=True,
        size=12
    )

    worksheet['A4'].alignment = Alignment(
        horizontal='center',
        vertical='center'
    )


    worksheet.merge_cells(
        'A5:J5'
    )

    worksheet['A5'] = (
        'گزارش تجهیزات IT'
    )

    worksheet['A5'].font = Font(
        bold=True,
        size=14
    )

    worksheet['A5'].alignment = Alignment(
        horizontal='center',
        vertical='center'
    )


    # =========================================================
    # معلومات گزارش
    # =========================================================

    worksheet['A7'] = 'تعداد تجهیزات'

    worksheet['B7'] = assets.count()


    worksheet['D7'] = 'تاریخ گزارش'

    worksheet['E7'] = (
        __import__('datetime').date.today()
    )


    # =========================================================
    # فیلترهای اعمال‌شده
    # =========================================================

    worksheet['A8'] = 'فیلترهای گزارش'

    worksheet['A8'].font = Font(
        bold=True
    )


    filter_text = []


    if category_id:

        category = AssetCategory.objects.filter(
            id=category_id
        ).first()

        if category:

            filter_text.append(
                f'دسته: {category.name}'
            )


    if status:

        status_dict = dict(
            Asset.STATUS_CHOICES
        )

        filter_text.append(
            f'وضعیت: {status_dict.get(status, status)}'
        )


    if location_id:

        facility = Facility.objects.filter(
            id=location_id
        ).first()

        if facility:

            filter_text.append(
                f'مکان: {facility.name}'
            )


    if filter_text:

        worksheet.merge_cells(
            'B8:J8'
        )

        worksheet['B8'] = (
            ' | '.join(filter_text)
        )

    else:

        worksheet.merge_cells(
            'B8:J8'
        )

        worksheet['B8'] = (
            'بدون فیلتر - تمام تجهیزات'
        )


    # =========================================================
    # Header جدول
    # =========================================================

    headers = [

        'شماره',

        'کد تجهیز',

        'نام تجهیز',

        'دسته',

        'برند',

        'مدل',

        'تعداد',

        'مکان',

        'حالت',

        'وضعیت',

    ]


    header_row = 10


    for column, header in enumerate(
        headers,
        start=1
    ):

        cell = worksheet.cell(
            row=header_row,
            column=column
        )

        cell.value = header

        cell.font = Font(
            bold=True,
            color=white
        )

        cell.fill = PatternFill(
            fill_type='solid',
            fgColor=dark_blue
        )

        cell.alignment = Alignment(
            horizontal='center',
            vertical='center'
        )

        cell.border = thin_border


    # =========================================================
    # اطلاعات تجهیزات
    # =========================================================

    for index, asset in enumerate(
        assets,
        start=1
    ):

        row = header_row + index


        values = [

            index,

            asset.asset_code,

            asset.name,

            asset.category.name,

            asset.brand or '-',

            asset.model or '-',

            asset.quantity,

            asset.location.name,

            asset.get_condition_display(),

            asset.get_status_display(),

        ]


        for column, value in enumerate(
            values,
            start=1
        ):

            cell = worksheet.cell(
                row=row,
                column=column
            )

            cell.value = value

            cell.border = thin_border

            cell.alignment = Alignment(
                horizontal='center',
                vertical='center'
            )


    # =========================================================
    # جدول Excel
    # =========================================================

    last_row = (
        header_row + assets.count()
    )


    if assets.exists():

        table_reference = (
            f'A{header_row}:J{last_row}'
        )

        table = Table(
            displayName='EquipmentReport',
            ref=table_reference
        )

        style = TableStyleInfo(

            name='TableStyleMedium2',

            showFirstColumn=False,

            showLastColumn=False,

            showRowStripes=True,

            showColumnStripes=False

        )

        table.tableStyleInfo = style

        worksheet.add_table(table)


    # =========================================================
    # تنظیم عرض ستون‌ها
    # =========================================================

    column_widths = {

        'A': 10,

        'B': 18,

        'C': 25,

        'D': 20,

        'E': 18,

        'F': 18,

        'G': 10,

        'H': 25,

        'I': 15,

        'J': 18,

    }


    for column, width in column_widths.items():

        worksheet.column_dimensions[
            column
        ].width = width


    # =========================================================
    # ارتفاع ردیف‌ها
    # =========================================================

    worksheet.row_dimensions[1].height = 25

    worksheet.row_dimensions[2].height = 23

    worksheet.row_dimensions[3].height = 25

    worksheet.row_dimensions[4].height = 22

    worksheet.row_dimensions[5].height = 24

    worksheet.row_dimensions[10].height = 25


    # =========================================================
    # Freeze Header
    # =========================================================

    worksheet.freeze_panes = 'A11'


    # =========================================================
    # تنظیمات چاپ
    # =========================================================

    worksheet.page_setup.orientation = (
        'landscape'
    )

    worksheet.page_setup.paperSize = (
        worksheet.PAPERSIZE_A4
    )

    worksheet.page_setup.fitToWidth = 1

    worksheet.page_setup.fitToHeight = 0

    worksheet.sheet_properties.pageSetUpPr.fitToPage = True


    worksheet.print_title_rows = '1:10'


    worksheet.print_area = (
        f'A1:J{last_row}'
    )


    # =========================================================
    # ایجاد Response
    # =========================================================

    response = HttpResponse(

        content_type=(
            'application/vnd.openxmlformats-officedocument'
            '.spreadsheetml.sheet'
        )

    )


    response[
        'Content-Disposition'
    ] = (
        'attachment; '
        'filename="IT_Equipment_Report.xlsx"'
    )


    sanitize_workbook(workbook)
    workbook.save(response)


    return response


  