Generate me a QFP chip! Generate me a QFP chip!
From the sandbox!
QFP is a type of form factor for an electrical component where pins come out the sides of a chip.  Here are is a picture of a typical QFP component:

you can see that the general formula is to have 4 sides of equal numbers of pins.
Your challenge is to create a program that takes in an integer, thich represents the number of pins on one side, and creates an ASCII QFP component with numbered pins.
Input:
a single integer which represents the number of pins on one side
Output:
An ASCII QFP chip with an apropriate pinout.
Example:
input:1

  4
 ┌┴┐
1┤ ├3
 └┬┘
  2
  
input:2

  87
 ┌┴┴┐
1┤  ├6
2┤  ├5
 └┬┬┘
  34

input:12

   444444444333
   876543210987
  ┌┴┴┴┴┴┴┴┴┴┴┴┴┐
 1┤            ├36
 2┤            ├35
 3┤            ├34
 4┤            ├33
 5┤            ├32
 6┤            ├31
 7┤            ├30
 8┤            ├29
 9┤            ├28
10┤            ├27
11┤            ├26
12┤            ├25
  └┬┬┬┬┬┬┬┬┬┬┬┬┘
   111111122222
   345678901234

Rules:

all QFP chips must be enclosed and sealed as well as ascii provides. spacing is of utmost importance. Dust inside a microprocessor is bad stuff!
pin numbering must be done as in the examples (Read left to right, top to bottom, numbered counter clockwise)
You may start numbering at 0, but this must not affect the chip (an input of 12 still needs 12 pins per side)
The only valid characers in your output are 1,2,3,4,5,6,7,8,9,0,┌,┴,┐,├,┘,┬,└,┤, spaces, and newlines.
all encodings for languages are allowed, but your output MUST be consistent with the rules above.

This is a codegolf, and as such, The code with the least number of bytes wins! Good Luck!
Kotlin, 397 393 bytes

Unnamed lambda.

You can try it here, but you'll have to paste the source in yourself because the editor doesn't seem to save programs in UTF-8 encoding. The ungolfed version is a full program, so you should be able to use that in its entirety.

Golfed

{n:Int-&gt;operator fun String.mod(x:Int){(1..x).map{print(this)}};val l={s:String-&gt;s.padStart(n/10+2)};var s=(1..n).map{"${n*4+1-it}".reversed()};val z={i:Int-&gt;l(" ")%1;s.map{print(it.getOrElse(i,{' '}))};"\n"%1};(s[0].length-1 downTo 0).map(z);l("┌")%1;"┴"%n;"┐\n"%1;(1..n).map{l("$it┤")%1;" "%n;"├${n*3+1-it}\n"%1};l("└")%1;"┬"%n;"┘\n"%1;s=(1..n).map{"${n+it}"};(0..s.last().length-1).map(z)}


(Sort of) Ungolfed

fun main(args: Array&lt;String&gt;) {
    var q = { n: Int -&gt;
        operator fun String.mod(x: Int) {
            (1..x).map { print(this) }
        }

        val l = { s: String -&gt;
            s.padStart(n / 10 + 2)
        }

        var s = (1..n).map { "${n * 4 + 1 - it}".reversed() }

        val z = { i: Int -&gt;
            l(" ")%1
            s.map { print(it.getOrElse(i, { ' ' })) }
            "\n"%1
        }

        (s[0].length - 1 downTo 0).map(z)

        l("┌")%1
        "┴"%n
        "┐\n"%1

        (1..n).map { l("$it┤") % 1;" " % n;"├${n * 3 + 1 - it}\n" % 1 }

        l("└")%1
        "┬"%n
        "┘\n"%1

        s = (1..n).map { "${n + it}" }
        (0..s.last().length - 1).map(z)
    }

    q(30)
}


Saved a bunch of bytes by overloading the % operator and using it to print. I'll probably revisit this later - I think I can save quite a few bytes if I use mod or some other operator as a concatenation function. More interpolation and less print calls.