import os
from django.conf import settings

from typing import Dict 

from openpyxl import Workbook

from docxtpl import DocxTemplate
import jinja2

from docxcompose.composer import Composer

from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
# from docx.enum.style import WD_STYLE_TYPE
from docx.shared import Mm, Pt
# from django.http import FileResponse

from datetime import datetime, timedelta
import io

from .models import *  # Для доступа к моделялям импортируем и их.


FONT_SIZE = 12

def short_date(date, offset=0):
    return f'{date+timedelta(days=offset):%d.%m.%Y}'

def gender_text(gender):
    return 'защитивший' if gender == 'муж.' else 'защитившая'

def rus_month(date):
    MONTH=[
        '',
        'января',
        'февраля',
        'марта',
        'апреля',
        'мая',
        'июня',
        'июля',
        'августа',
        'сентября',
        'октября',
        'ноября',
        'декабря',
    ]
    return f'{date:%d} {MONTH[date.month]} {date:%Y}\xa0'

jinja_env = jinja2.Environment()
jinja_env.filters['tmpl_date'] = rus_month
jinja_env.filters['tmpl_short_date'] = short_date
jinja_env.filters['tmpl_gender'] = gender_text





def order_start(document, number, date, type):

    document.core_properties.title = f'№ {number} от {rus_month(date)}'
    document.core_properties.subject = type

    section = document.sections[0]
    section.left_margin = Mm(30)
    section.right_margin = Mm(14)
    section.top_margin = Mm(10)
    section.bottom_margin = Mm(10)
    
    # Меняем стиль абзаца по умолчанию:
    # получаем объект стиля `Normal`
    style = document.styles['Normal']
    # # изменяем настройки шрифта
    style.font.name = 'Times New Roman'
    style.font.size = Pt(FONT_SIZE)
    # # настраиваем красную строку абзаца
    style.paragraph_format.first_line_indent = Mm(0)
    style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY
    style.paragraph_format.line_spacing = 1.0
    style.paragraph_format.space_after = 0


def order_footer(document, list_proposers:Dict, list_approvers:Dict, rector:str):  

    p = document.add_paragraph(f'Ректор___________________________________________________{rector}')
    p.paragraph_format.space_before = Pt(30)
    p.paragraph_format.space_after = Pt(20)
    p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER

    lines_number = max(len(list_approvers), len(list_proposers))
    table = document.add_table(rows=lines_number * 2 + 1, cols=2)
 
    table.cell(0, 0).text = 'Проект вносят:'
    table.cell(0, 0).width = Mm(120)
    table.cell(0, 0).paragraphs[0].paragraph_format.space_after = Pt(8)
    table.cell(0, 1).text = 'Согласовано:'

    number = 1
    for key, value in list_approvers.items():
        table.cell(number * 2 - 1, 1).text = key
        table.cell(number * 2 - 1, 1).paragraphs[0].paragraph_format.space_after = Pt(2)
        table.cell(number * 2, 1).text = f'_____________ {value}'
        table.cell(number * 2, 1).paragraphs[0].paragraph_format.space_after = Pt(4)
        number += 1

    number = 1
    for key, value in list_proposers.items():
        table.cell(number * 2 - 1, 0).text = key
        table.cell(number * 2 - 1, 0).paragraphs[0].paragraph_format.space_after = Pt(2)
        table.cell(number * 2, 0).text = f'_____________ {value}'
        table.cell(number * 2, 0).paragraphs[0].paragraph_format.space_after = Pt(4)
        number += 1

    # return document


def order_by_id(order_id):
    '''Подготовка документа приказа по шаблону'''
    order = Orders.objects.get(pk=order_id)
    contracts = Orders.objects.get(pk=order_id).contracts.all().order_by('client')
    buf = io.BytesIO()
    text = '' if contracts.count()==1 else 'ы'

    # document.add_paragraph(f'Основание: договор{text} на обучение')


    filename = order.template.file
    tpl = DocxTemplate(filename)
    
    context = {
        'order': order,
        'contracts': contracts,
        'plural': text,

    }
    tpl.render(context, jinja_env)
    tpl.save(buf)
    buf.seek(0)

    return buf 



def order_on_enrollment(object, contracts):
    buf = io.BytesIO()
    document = Document()

    order_start(document, object.number, object.registered, object.type_order)

    p = document.add_paragraph()
    p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    p.paragraph_format.space_before = Mm(90)
    run = p.add_run('О движении контингента слушателей ИДО')
    run.font.bold = True

    document.add_paragraph()
   
    p = document.add_paragraph()
    p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    run = p.add_run('ПРИКАЗЫВАЮ:')
    run.font.bold = True

    p = document.add_paragraph(
        f'Зачислить с {rus_month(object.event_date)} в число слушателей ИДО ЮРГПУ(НПИ) по дополнительной профессиональной '
            'программе профессиональной переподготовки «Машины и оборудование нефтяных и газовых промыслов». Срок '
            'обучения – 521 час. Форма обучения заочная с применением электронного обучения и дистанционных '
            'образовательных технологий.'
    )
    p.paragraph_format.first_line_indent = Mm(12.5)
    p.paragraph_format.space_after = Pt(12)

    table = document.add_table(rows=1, cols=2)
    for number, item in enumerate(contracts):
        cell = table.cell(number, 0)
        cell.text = f'{number+1}. {item.client.surname} {item.client.name} {item.client.patronymic}'
        p = cell.paragraphs[0]
        p.paragraph_format.first_line_indent = Mm(10)

        cell = table.cell(number, 1)
        cell.text = f'{item.number}'

        table.add_row()

    text = '' if contracts.count()==1 else 'ы'

    document.add_paragraph(f'Основание: договор{text} на обучение')

    list_proposers = {
        'Директор ИДО': 'И. А. Ревин',
    }

    list_approvers = {
        'Проректор по ОД': 'Е. М. Дьяконов',
        'Начальник ЮУ': 'Т. А. Кузьменко',
        'Директор ДЭиФ': 'А. П. Игнатьева',
        'Директор АД': 'Р. Г. Зайцев',
    }

    order_footer(document, list_proposers, list_approvers, object.structure.rector)
    
    document.save(buf)
    buf.seek(0)

    return buf


def order_on_theme(order, contracts):
    buf = io.BytesIO()
    document = Document()

    order_start(document, order.number, order.registered, order.type_order)

    p = document.add_paragraph()
    p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    p.paragraph_format.space_before = Mm(90)
    run = p.add_run('Об утверждении тем выпускных работ для слушателей ИДО')
    run.font.bold = True

    document.add_paragraph()
    p = document.add_paragraph('В соответствии с дополнительной профессиональной программой профессиональной' 
    ' переподготовки «Машины и оборудование нефтяных и газовых промыслов»')
    p.paragraph_format.first_line_indent = Mm(12.5)

    p = document.add_paragraph()
    p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    run = p.add_run('ПРИКАЗЫВАЮ:')
    run.font.bold = True

    document.add_paragraph('1. Утвердить темы выпускных квалификационных работ слушателям по дополнительной '
    'профессиональной образовательной программе профессиональной переподготовки «Машины и оборудование '
    'нефтяных и газовых промыслов»:')

    for number, item in enumerate(contracts):
        p = document.add_paragraph(f'1.{number+1}. {item.client.surname} {item.client.name} {item.client.patronymic}')
        p.paragraph_format.space_before = Pt(8)
        p.paragraph_format.first_line_indent = Mm(12.5)
        p.paragraph_format.keep_with_next = True

        p = document.add_paragraph(f'{item.degree_work.title}. Руководитель: {item.degree_work.adviser.surname} {item.degree_work.adviser.name} {item.degree_work.adviser.patronymic} - ')
        if item.degree_work.adviser.degree:
            p.add_run(f'{str(item.degree_work.adviser.degree).lower()}, ')
        p.add_run(f'{str(item.degree_work.adviser.post).lower()} кафедры «{order.extract.department}».')
        p.add_run(f' Тема предложена кафедрой «{order.extract.department}».')
    
    text = f'Основание: протокол заседания кафедры «{order.extract.department}» №{order.extract.number} от {rus_month(order.extract.date)}'

    list_proposers = {
        'Директор ИДО': 'И. А. Ревин',
    }

    list_approvers = {
        'Проректор по ОД': 'Е. М. Дьяконов',
        'Директор АД': 'Р. Г. Зайцев',
    }

    order_footer(document, list_proposers, list_approvers, order.structure.rector)    

    document.save(buf)
    buf.seek(0)

    return buf

def extract_department_meeting (object, contracts):

    buf = io.BytesIO()
    document = Document()

    section = document.sections[0]
    section.left_margin = Mm(20)
    section.right_margin = Mm(10)
    section.top_margin = Mm(10)
    section.bottom_margin = Mm(10)
    # Меняем стиль абзаца по умолчанию:
    # получаем объект стиля `Normal`
    style = document.styles['Normal']
    # # изменяем настройки шрифта
    style.font.name = 'Times New Roman'
    style.font.size = Pt(13)
    # # настраиваем красную строку абзаца
    # style.paragraph_format.first_line_indent = Mm(12.5)
    style.paragraph_format.first_line_indent = Mm(12.5)
    style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY
    style.paragraph_format.line_spacing = 1.2
    style.paragraph_format.space_after = 0

    text = f'Выписка из протокола №{object.extract.number} заседания кафедры\n «{object.extract.department}» от {rus_month(object.extract.date)}'
    p = document.add_paragraph(text)
    p.paragraph_format.first_line_indent = Mm(0)
    p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER

    document.add_paragraph('СЛУШАЛИ:')
    document.add_paragraph(
        'Доцента кафедры ТМТМО, кандидата технических наук Мирного Сергея Георгиевича о рассмотрении'
        ' тем выпускных квалификационных работ слушателям по дополнительному профессиональному '
        'образованию по направлению профессиональной переподготовки «Машины и оборудование нефтяных и '
        'газовых промыслов»')
    document.add_paragraph('ПОСТАНОВИЛИ:')
    document.add_paragraph('Ходатайствовать об утверждении тем выпускных квалификационных работ слушателям '
        'по дополнительному профессиональному образованию по направлению ' 
        'профессиональной переподготовки «Машины и оборудование нефтяных и '
        'газовых промыслов»:')
    for number, item in enumerate(contracts):
        p = document.add_paragraph(f'{number+1}. {item.client.surname} {item.client.name} {item.client.patronymic}')
        p.paragraph_format.keep_with_next = True
        p = document.add_paragraph(f'{item.degree_work.title}. Руководитель: {item.degree_work.adviser.surname} {item.degree_work.adviser.name} {item.degree_work.adviser.patronymic} - ')
        if item.degree_work.adviser.degree:
            p.add_run(f'{str(item.degree_work.adviser.degree).lower()}, ')
        p.add_run(f'{str(item.degree_work.adviser.post).lower()} кафедры «{object.extract.department}».')

    document.add_paragraph()
    p = document.add_paragraph(f'Доцент кафедры «ТМТМО», \nкандидат технических наук, доцент \t\t\t\t'
        f'________________ {object.extract.speaker.name[:1]}. {object.extract.speaker.patronymic[:1]}. {object.extract.speaker.surname}')
    p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
    p.paragraph_format.first_line_indent = Mm(0)
    
    p = document.add_paragraph(f'Секретарь \t\t\t\t\t\t\t\t'
        f'________________ {object.extract.secretary.name[:1]}. {object.extract.secretary.patronymic[:1]}. {object.extract.secretary.surname}')
    p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
    p.paragraph_format.first_line_indent = Mm(0)
    p.paragraph_format.space_before = Pt(10)
    
    document.save(buf)
    buf.seek(0)

    return buf


def protocol_by_order(order_id):
    '''Генерация протоколов защиты по айди приказа
    '''
    contracts = Orders.objects.get(pk=order_id).contracts.all().order_by('degree_work__protocol__number')
    buf = io.BytesIO()

    last = len(contracts) - 1
    for n, item in enumerate(contracts):
        doc2 = Document(protocol_by_id(item.id))
        if n != last:
            doc2.add_page_break()
        if n == 0:
            composer = Composer(doc2)
        else:
            composer.append(doc2)

    composer.save(buf)
    buf.seek(0)

    return buf


def memo_by_order(acces_id):
    '''Генерация служебки на пропуска по айди
    '''
    acces = Access_lists.objects.get(pk=acces_id)
    contracts = Contracts.objects.filter(access_lists__pk = acces_id).order_by('client__surname', 'client__name', 'group__graduation_date', )

    buf = io.BytesIO()

    filename = acces.template.file
    tpl = DocxTemplate(filename)

    date = acces.registration_date
    number = acces.number
    context = {
        'contracts': contracts,
        'date': date,
        'number': number,
    }
    tpl.render(context, jinja_env)
    tpl.save(buf)    
    buf.seek(0)

    return buf


def protocol_by_id(contract_id):
    '''Генерация протокола защиты ВКР по айди договора
    '''
    contract = Contracts.objects.get(pk=contract_id)
    questions = Protocols.objects.get(pk=contract.degree_work.protocol.pk).questions.all()

    buf = io.BytesIO()

    filename = contract.degree_work.protocol.template.file
    tpl = DocxTemplate(filename)

    dt = contract.degree_work.protocol.date_time
    dte = dt + timedelta(minutes=25)
    date_time = f'{rus_month(dt)}г. c {dt:%H} час. {dt:%M} мин. до {dte:%H} час. {dte:%M} мин.'

    context = {
        'contract': contract,
        'title': contract.degree_work.title,
        'date_time': date_time,
        'questions': questions,
        'fio_genitive': f'{contract.client.surname_cases.genitive} {contract.client.name_cases.genitive} {contract.client.patronymic_cases.genitive}',
        'fio_dative': f'{contract.client.surname_cases.dative} {contract.client.name_cases.dative[:1]}. {contract.client.patronymic_cases.dative[:1]}.'
    }
    tpl.render(context)
    tpl.save(buf)
    buf.seek(0)

    return buf 

def filefor_registry(order_id):
    '''генерация файла с данными для внесения в базу по дипломам'''
    order = Orders.objects.get(pk=order_id)
    contracts = Orders.objects.get(pk=order_id).contracts.all().order_by('client')

    filename = os.path.join(settings.MEDIA_ROOT, 'templates\for_registry1.xlsx' )
    wb = Workbook()
    buf = io.BytesIO()

    ws = wb.active
    # ws.append(['Фамилия', 'Имя', 'Отчество', 'Дата рождения', 'СНИЛС', 'Диплом серия/номер', 'Начало обучения', 'Конец обучения'])
    string_stub = ''
    for item in contracts:
        print(item.client.diploma)
        ws.append([
            'Диплом о профессиональной переподготовке',
            'Оригинал',
            'Нет',
            'Нет',
            'Нет',
            'Нет',
            '',
            f'{item.end_date:%d.%m.%Y}',
            # '05/07/2024',
            '',
            'Профессиональная переподготовка',
            'Машины и оборудование нефтяных и газовых промыслов',
            'Добыча, переработка, транспортировка нефти и газа',
            'Бурение скважин, добыча нефти и газа',
            'Образование',
            'Высшее образование',
            item.client.surname,
            f'{item.client.diploma.series if item.client.diploma else string_stub}',
            f'{item.client.diploma.number if item.client.diploma else string_stub}',
            f'{item.start_date:%Y}',
            f'{item.end_date:%Y}',
            '521',
            item.client.surname,
            item.client.name,
            item.client.patronymic,
            f'{item.client.birthdate:%d.%m.%Y}',
            f'{"Муж" if item.client.gender=="муж." else "Жен"}',
            item.client.snils,
            'Заочная',
            'Платное обучение',
            'в образовательной организации',
            '643',
            # f'{item.start_date:%d.%m.%Y}',
            # f'{item.end_date:%d.%m.%Y}',
        ])

    wb.save(buf)
    buf.seek(0)

    return buf

def gen_diploma(contract, form:bool):

    buf = io.BytesIO()
    document_name = 'templates\diploma_form.docx' if form else 'templates\diploma_supplement.docx' 
    filename = os.path.join(settings.MEDIA_ROOT, document_name)
    tpl = DocxTemplate(filename)    

    context = {
        'surname': contract.client.surname,
        'name': contract.client.name,
        'patronymic': contract.client.patronymic,
        'diploma_number': contract.degree_work.diploma_number,
        'registration_number': contract.degree_work.registration_number,
        'start_date': rus_month(contract.start_date),
        'end_date': rus_month(contract.end_date),
        'protocol_date': f'{contract.degree_work.protocol.date_time:%d.%m.%Y}',
        'protocol_number': contract.degree_work.protocol.number,
    }
    
    tpl.render(context)
    tpl.save(buf)
    buf.seek(0)

    return buf
