package kr.itn.itnhub.org;

import kr.itn.itnhub.AbstractDbTest;
import kr.itn.itnhub.contact.Contact;
import kr.itn.itnhub.contact.ContactMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class OrganizationMapperTest extends AbstractDbTest {

    @Autowired
    OrganizationMapper mapper;

    @Autowired
    ContactMapper contactMapper;

    @Autowired
    JdbcTemplate jdbc;

    @BeforeEach
    void clean() {
        jdbc.update("delete from organization");
        jdbc.update("delete from contact");
    }

    private Organization seedRow(String orgNo, String orgName) {
        Organization org = new Organization();
        org.setOrgNo(orgNo);
        org.setOrgName(orgName);
        org.setChannelSlug(orgNo);
        return org;
    }

    private Long insertContact(String category, String name) {
        Contact contact = new Contact();
        contact.setCategory(category);
        contact.setName(name);
        contactMapper.insert(contact);
        return contact.getId();
    }

    @Test
    void 신규_기관을_넣고_다시_읽는다() {
        mapper.upsertBySeed(seedRow("001", "국제방송교류재단"));

        List<Organization> all = mapper.findAll();

        assertThat(all).hasSize(1);
        assertThat(all.get(0).getOrgNo()).isEqualTo("001");
        assertThat(all.get(0).getOrgName()).isEqualTo("국제방송교류재단");
        assertThat(all.get(0).getStatus()).isEqualTo(OrgStatus.INFO_PENDING);
    }

    @Test
    void 연번이_같아도_기관명이_다르면_별도_행이다() {
        mapper.upsertBySeed(seedRow("008", "경찰청"));
        mapper.upsertBySeed(seedRow("008", "경찰청_치안정책연구소"));

        assertThat(mapper.findAll()).hasSize(2);
    }

    @Test
    void 시드_재실행은_기존_채널ID를_지우지_않는다() {
        mapper.upsertBySeed(seedRow("001", "국제방송교류재단"));
        Long id = mapper.findAll().get(0).getId();
        mapper.updateChannelIdMj(id, "chan-mj");
        mapper.updateChannelIdLaw(id, "chan-law");

        mapper.upsertBySeed(seedRow("001", "국제방송교류재단"));

        Organization after = mapper.findById(id);
        assertThat(after.getChannelIdMj()).isEqualTo("chan-mj");
        assertThat(after.getChannelIdLaw()).isEqualTo("chan-law");
        assertThat(after.getStatus()).isEqualTo(OrgStatus.ACTIVE);
    }

    @Test
    void 채널ID를_한쪽만_저장할_수_있다() {
        mapper.upsertBySeed(seedRow("002", "세종학당재단"));
        Long id = mapper.findAll().get(0).getId();
        mapper.updateAssignments(id, insertContact("APPLICANT", "담당자"), null, null, null);

        mapper.updateChannelIdMj(id, "only-mj");

        Organization after = mapper.findById(id);
        assertThat(after.getChannelIdMj()).isEqualTo("only-mj");
        assertThat(after.getChannelIdLaw()).isNull();
        assertThat(after.getStatus()).isEqualTo(OrgStatus.PARTIAL);
    }

    @Test
    void 담당자_3종을_배정하면_조인된_담당자_정보가_그대로_읽힌다() {
        mapper.upsertBySeed(seedRow("003", "한국문학번역원"));
        Organization org = mapper.findAll().get(0);

        Long applicantId = insertContact("APPLICANT", "송민지");
        Long mjId = insertContact("MJ", "김문정");
        Long lawyerId = insertContact("LAWYER", "이변호");

        mapper.updateAssignments(org.getId(), applicantId, mjId, lawyerId, "2026-07-21");

        Organization after = mapper.findById(org.getId());
        assertThat(after.getApplicantContactId()).isEqualTo(applicantId);
        assertThat(after.getMjContactId()).isEqualTo(mjId);
        assertThat(after.getLawyerContactId()).isEqualTo(lawyerId);
        assertThat(after.getLawyerAssignedDate()).isEqualTo("2026-07-21");

        assertThat(after.getApplicant().getName()).isEqualTo("송민지");
        assertThat(after.getApplicant().getCategory()).isEqualTo("APPLICANT");
        assertThat(after.getMj().getName()).isEqualTo("김문정");
        assertThat(after.getLawyer().getName()).isEqualTo("이변호");
        assertThat(after.getStatus()).isEqualTo(OrgStatus.READY);
    }

    @Test
    void 배정되지_않은_역할은_담당자가_null이다() {
        mapper.upsertBySeed(seedRow("004", "예시기관"));
        Organization org = mapper.findAll().get(0);

        Long applicantId = insertContact("APPLICANT", "담당자");
        mapper.updateAssignments(org.getId(), applicantId, null, null, null);

        Organization after = mapper.findById(org.getId());
        assertThat(after.getApplicant()).isNotNull();
        assertThat(after.getMj()).isNull();
        assertThat(after.getLawyer()).isNull();
    }

    @Test
    void 배정_해제는_null로_넘기면_반영된다() {
        mapper.upsertBySeed(seedRow("005", "예시기관2"));
        Organization org = mapper.findAll().get(0);

        Long applicantId = insertContact("APPLICANT", "담당자");
        mapper.updateAssignments(org.getId(), applicantId, null, null, null);
        mapper.updateAssignments(org.getId(), null, null, null, null);

        Organization after = mapper.findById(org.getId());
        assertThat(after.getApplicantContactId()).isNull();
        assertThat(after.getApplicant()).isNull();
        assertThat(after.getStatus()).isEqualTo(OrgStatus.INFO_PENDING);
    }

    @Test
    void 연번과_기관명으로_단건_조회할_수_있다() {
        mapper.upsertBySeed(seedRow("006", "예시기관3"));

        Organization found = mapper.findByOrgNoAndOrgName("006", "예시기관3");

        assertThat(found).isNotNull();
        assertThat(found.getOrgName()).isEqualTo("예시기관3");
    }

    @Test
    void 목록은_연번_오름차순이다() {
        mapper.upsertBySeed(seedRow("010", "국립아시아문화전당"));
        mapper.upsertBySeed(seedRow("002", "세종학당재단"));
        mapper.upsertBySeed(seedRow("001", "국제방송교류재단"));

        assertThat(mapper.findAll())
                .extracting(Organization::getOrgNo)
                .containsExactly("001", "002", "010");
    }
}
