import grails.test.*
import static org.junit.Assert.assertThat
import static org.hamcrest.CoreMatchers.equalTo

/**
 * Unit tests for PurchaseOrderService class.
 */
class PurchaseOrderServiceTests extends GrailsUnitTestCase {
    def pos = new PurchaseOrderService()

    protected void setUp() {
        super.setUp()
        mockDomain(PurchaseOrder)
        mockDomain(PurchaseOrderNumber)
        mockDomain(Supplier)
        mockDomain(SupplierType)
    }

    protected void tearDown() {
        super.tearDown()
    }

    void testFindsFirstUnusedPurchaseOrderWhenAllUnused() {
        createTenPurchaseOrderNumbers()
        assertThat PurchaseOrderNumber.list().size(), equalTo(10)

        def next = pos.findNextUnusedPurchaseOrderNumber()

        assertThat next.value, equalTo("P1000")
    }

    void testFindsFirstUnusuedPurchaseOrderWhenSomeUsed() {
        createTenPurchaseOrderNumbers()
        createPurchaseOrders(4)

        def next = pos.findNextUnusedPurchaseOrderNumber()

        assertThat next.value, equalTo("P1004")
    }

    void testFindsNullIfNoUnusedPurchaseOrderNumbers() {
        createTenPurchaseOrderNumbers()
        createPurchaseOrders(10)

        def next = pos.findNextUnusedPurchaseOrderNumber()

        assertThat next, equalTo(null)
    }

    void testGetOrCreatePurchaseOrderWithExistingOrder() {
        createTenPurchaseOrderNumbers()
        createPurchaseOrders(3)
        def params=[purchaseOrderNumber:[id:2]]

        def po = pos.getOrCreatePurchaseOrder(params)

        assertThat po.comment, equalTo("Created by test")
        assertThat po.purchaseOrderNumber.value, equalTo("P1001")
    }

    void testGetOrCreatePurchaseOrderWithNoExistingOrder() {
        createTenPurchaseOrderNumbers()
        createPurchaseOrders(3)
        createSuppliers(1)
        def params=[purchaseOrderNumber:[id:4],supplier:[id:1]]

        def po = pos.getOrCreatePurchaseOrder(params)

        assertThat po.comment, equalTo("")
        assertThat po.purchaseOrderNumber.value, equalTo("P1003")
    }

    void testFindsDraftPurchaseOrderNumbers() {
        createTenPurchaseOrderNumbers()
        createPurchaseOrders(3)
        releaseOrder(PurchaseOrder.get(2))

        def drafts = pos.findDraftPurchaseOrderNumbers()

        assertThat drafts.size(), equalTo(2)
        assertThat drafts[0].value, equalTo("P1000")
        assertThat drafts[1].value, equalTo("P1002")
    }



    def createPurchaseOrders(int howMany) {
        for (int i=0; i<howMany; i++) {
            def po = new PurchaseOrder(comment:"Created by test", supplier:new Supplier())
            def pon = PurchaseOrderNumber.list()[i]
            pon.purchaseOrder = po;
            po.purchaseOrderNumber = pon;
            po.save(failOnError:true)
            pon.save(failOnError:true)
        }
    }

    def createSuppliers(int howMany) {
        for (int i=0; i<howMany; i++) {
            def supplier = new Supplier(name:"Supplier ${i}", supplierType:new SupplierType())
            supplier.save(failOnError:true)
        }
    }

    private createTenPurchaseOrderNumbers() {
        for (int i = 1000; i < 1010; i++) {
            new PurchaseOrderNumber(value: "P${i}").save(failOnError: true)
        }
    }

    def releaseOrder(PurchaseOrder po) {
        po.ordered = new Date()
        po.save(failOnError:true)
    }
}
