package de.softwareapp_hb.privateqrscanner.util

import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Test

class ScanContentParsersTest {

    @Test
    fun extractPhoneNumber_handlesTelUri() {
        val phone = ScanContentParsers.extractPhoneNumber("tel:+123456789?foo=bar")
        assertEquals("+123456789", phone)
    }

    @Test
    fun parseSms_handlesSmstoWithBody() {
        val (number, body) = ScanContentParsers.parseSms("SMSTO:+49123456:hello there")
        assertEquals("+49123456", number)
        assertEquals("hello there", body)
    }

    @Test
    fun extractEmail_handlesMailtoAndPlainText() {
        assertEquals("x@y.com", ScanContentParsers.extractEmail("mailto:x@y.com?subject=hi"))
        assertEquals("a.b+c@d.dev", ScanContentParsers.extractEmail("contact me at a.b+c@d.dev now"))
    }

    @Test
    fun parseContact_handlesVCard() {
        val raw = """
            BEGIN:VCARD
            VERSION:3.0
            FN:Jane Doe
            ORG:Acme Corp
            TITLE:Ops Lead
            TEL;TYPE=CELL:+1234567
            EMAIL:jane@acme.com
            ADR:;;Main Street 1;Berlin;;;Germany
            NOTE:VIP
            END:VCARD
        """.trimIndent()

        val parsed = ScanContentParsers.parseContact(raw)
        assertNotNull(parsed)
        assertEquals("Jane Doe", parsed?.fullName)
        assertEquals("Acme Corp", parsed?.organization)
        assertEquals("Ops Lead", parsed?.title)
        assertEquals("+1234567", parsed?.phones?.firstOrNull())
        assertEquals("jane@acme.com", parsed?.emails?.firstOrNull())
        assertTrue(parsed?.address?.contains("Main Street 1") == true)
        assertEquals("VIP", parsed?.note)
    }

    @Test
    fun parseContact_handlesMeCard() {
        val raw = "MECARD:N:Doe,John;TEL:+49111;EMAIL:john@doe.dev;ADR:Street 9;NOTE:Friend;;"

        val parsed = ScanContentParsers.parseContact(raw)
        assertNotNull(parsed)
        assertEquals("John Doe", parsed?.fullName)
        assertEquals("+49111", parsed?.phones?.firstOrNull())
        assertEquals("john@doe.dev", parsed?.emails?.firstOrNull())
        assertEquals("Street 9", parsed?.address)
        assertEquals("Friend", parsed?.note)
    }

    @Test
    fun parseContact_handlesParameterizedVCardKeysAndNameOrder() {
        val raw = """
            BEGIN:VCARD
            VERSION:3.0
            N:Doe;John;;Dr.;
            ORG;CHARSET=UTF-8:ACME Inc
            TITLE;LANGUAGE=en:Engineering Manager
            TEL;TYPE=WORK,VOICE:+12025550123
            EMAIL;TYPE=INTERNET:john.doe@acme.com
            END:VCARD
        """.trimIndent()

        val parsed = ScanContentParsers.parseContact(raw)
        assertNotNull(parsed)
        assertEquals("Dr. John Doe", parsed?.fullName)
        assertEquals("ACME Inc", parsed?.organization)
        assertEquals("Engineering Manager", parsed?.title)
        assertEquals("+12025550123", parsed?.phones?.firstOrNull())
        assertEquals("john.doe@acme.com", parsed?.emails?.firstOrNull())
    }

    @Test
    fun parseCalendarEvent_handlesVEvent() {
        val raw = """
            BEGIN:VCALENDAR
            VERSION:2.0
            BEGIN:VEVENT
            SUMMARY:Team Sync
            DESCRIPTION:Weekly planning
            LOCATION:Room A
            DTSTART:20270110T103000Z
            DTEND:20270110T110000Z
            END:VEVENT
            END:VCALENDAR
        """.trimIndent()

        val parsed = ScanContentParsers.parseCalendarEvent(raw)
        assertNotNull(parsed)
        assertEquals("Team Sync", parsed?.title)
        assertEquals("Weekly planning", parsed?.description)
        assertEquals("Room A", parsed?.location)
        assertNotNull(parsed?.startMillis)
        assertNotNull(parsed?.endMillis)
        assertFalse(parsed?.allDay ?: true)
    }

    @Test
    fun parseContact_handlesTecItVCardPayload() {
        val raw = """
            BEGIN:VCARD
            VERSION:3.0
            N:Doe;John;;;
            FN:John Doe
            ORG:TEC-IT
            TITLE:Position
            ADR;TYPE=WORK:;;203 New York Ave;New York;NY;11377;USA
            TEL;TYPE=WORK,VOICE:+43 7252 72720
            TEL;TYPE=CELL:+43 660 1234567
            TEL;TYPE=FAX:+43 7252 72720-77
            EMAIL;TYPE=INTERNET:support@tec-it.com
            URL:http://www.tec-it.com
            LOGO;VALUE=URI:http://lh5.googleusercontent.com/-7RwzuzOVTsw/SypSXHmWr7I/AAAAAAAAAB0/5vE5NqugtLQ/TEC-IT_Banner_120x29.gif
            END:VCARD
        """.trimIndent()

        val parsed = ScanContentParsers.parseContact(raw)
        assertNotNull(parsed)
        assertEquals("John Doe", parsed?.fullName)
        assertEquals("TEC-IT", parsed?.organization)
        assertEquals("Position", parsed?.title)
        assertEquals("support@tec-it.com", parsed?.emails?.firstOrNull())
        assertTrue(parsed?.phones?.contains("+43 7252 72720") == true)
        assertTrue(parsed?.phones?.contains("+43 660 1234567") == true)
        assertTrue(parsed?.phones?.contains("+43 7252 72720-77") == true)
        assertTrue(parsed?.address?.contains("203 New York Ave") == true)
        assertTrue(parsed?.address?.contains("New York") == true)
        assertTrue(parsed?.address?.contains("NY") == true)
        assertTrue(parsed?.address?.contains("11377") == true)
        assertTrue(parsed?.address?.contains("USA") == true)
    }

    @Test
    fun parseContact_handlesTecItMeCardPayload() {
        val raw = "MECARD:N:Doe,John;ORG:TEC-IT;TITLE:Position;ADR:203 New York Ave, New York, NY 11377, USA;TEL:+43 7252 72720;TEL:+43 660 1234567;TEL:+43 7252 72720-77;EMAIL:support@tec-it.com;URL:http://www.tec-it.com;NOTE:Logo http://lh5.googleusercontent.com/-7RwzuzOVTsw/SypSXHmWr7I/AAAAAAAAAB0/5vE5NqugtLQ/TEC-IT_Banner_120x29.gif;;"

        val parsed = ScanContentParsers.parseContact(raw)
        assertNotNull(parsed)
        assertEquals("John Doe", parsed?.fullName)
        assertEquals("TEC-IT", parsed?.organization)
        assertEquals("Position", parsed?.title)
        assertEquals("support@tec-it.com", parsed?.emails?.firstOrNull())
        assertTrue(parsed?.phones?.contains("+43 7252 72720") == true)
        assertTrue(parsed?.phones?.contains("+43 660 1234567") == true)
        assertTrue(parsed?.phones?.contains("+43 7252 72720-77") == true)
        assertEquals("203 New York Ave, New York, NY 11377, USA", parsed?.address)
    }

    @Test
    fun parseWifi_handlesStandardPayload() {
        val raw = "WIFI:T:WPA;S:OfficeNet;P:superSecret;H:false;;"

        val parsed = ScanContentParsers.parseWifi(raw)
        assertNotNull(parsed)
        assertEquals("OfficeNet", parsed?.ssid)
        assertEquals("WPA", parsed?.security)
        assertEquals("superSecret", parsed?.password)
        assertEquals(false, parsed?.hidden)
    }

    @Test
    fun parseWifi_handlesEscapedCharactersAndHiddenFlag() {
        val raw = "WIFI:T:WPA2;S:Cafe\\;Guest\\,2nd\\:Floor;P:p\\\\ass\\;word;H:true;;"

        val parsed = ScanContentParsers.parseWifi(raw)
        assertNotNull(parsed)
        assertEquals("Cafe;Guest,2nd:Floor", parsed?.ssid)
        assertEquals("WPA2", parsed?.security)
        assertEquals("p\\ass;word", parsed?.password)
        assertEquals(true, parsed?.hidden)
    }
}
